
Key Required VerifiedUniversal
--[[
WARNING: Heads up! This script has not been verified by ScriptBlox. Use at your own risk!
]]
--// SERVICES
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
--// =========================================================
--// RUTAS (CON PROTECCIÓN)
--// =========================================================
local CrystalsFolder = workspace
:WaitForChild("Things")
:WaitForChild("Crystals")
local BouldersFolder = workspace
:WaitForChild("MountainDecorations")
:WaitForChild("Boulders")
-- Ruta de DroppedCrystals con protección
local DroppedCrystalsFolder = nil
local DroppedCrystalsSuccess, DroppedCrystalsResult = pcall(function()
return workspace:WaitForChild("DroppedCrystals")
end)
if DroppedCrystalsSuccess and DroppedCrystalsResult then
DroppedCrystalsFolder = DroppedCrystalsResult
end
-- Ruta de DroppedRunes con protección
local DroppedRunesFolder = nil
local DroppedRunesSuccess, DroppedRunesResult = pcall(function()
return workspace:WaitForChild("DroppedRunes")
end)
if DroppedRunesSuccess and DroppedRunesResult then
DroppedRunesFolder = DroppedRunesResult
end
--// =========================================================
--// CONFIG
--// =========================================================
local REFRESH_TIME = 10
local ITEM_HEIGHT = 82
local ITEM_PADDING = 6
local EXTRA_ROWS = 4
--// =========================================================
--// TIPO ACTUAL
--// =========================================================
local CurrentType = "Crystals"
-- Crystals = Things.Crystals + DroppedCrystals (si existe)
-- Boulders = MountainDecorations.Boulders
-- Runes = DroppedRunes (si existe)
--// =========================================================
--// INTERACCIÓN INSTANTÁNEA
--// =========================================================
local InstantInteract = false
local OriginalHoldDuration = {}
local function UpdateProximityPrompts()
for _, obj in ipairs(workspace:GetDescendants()) do
if obj:IsA("ProximityPrompt") then
if OriginalHoldDuration[obj] == nil then
OriginalHoldDuration[obj] = obj.HoldDuration
end
obj.HoldDuration = 0
end
end
end
local function RestoreProximityPrompts()
for prompt, duration in pairs(OriginalHoldDuration) do
if prompt
and prompt.Parent
and prompt:IsA("ProximityPrompt") then
prompt.HoldDuration = duration
end
end
table.clear(OriginalHoldDuration)
end
local function SetInstantInteract(enabled)
InstantInteract = enabled
if enabled then
UpdateProximityPrompts()
else
RestoreProximityPrompts()
end
end
-- Nuevos prompts que aparezcan después
workspace.DescendantAdded:Connect(function(obj)
if obj:IsA("ProximityPrompt")
and InstantInteract then
task.defer(function()
if obj.Parent
and InstantInteract then
if OriginalHoldDuration[obj] == nil then
OriginalHoldDuration[obj] = obj.HoldDuration
end
obj.HoldDuration = 0
end
end)
end
end)
--// =========================================================
--// CRYSTAL LUCK
--// =========================================================
local RarityMult = {
1,
1.6,
2.6,
4.2,
7,
12,
216,
480,
600
}
local Base = 0.00045
local WeightExp = 0.5
local KgCap = 500
local BombCrystalMult = 3
local BloodLuckMult = 4
--// MUTACIONES
local MutationLuck = {
Verdant = 15,
Voltaic = 20,
Gilded = 18,
Onyx = 28,
Terminus = 40,
Frost = 1.4,
Dustworn = 1.35,
Molten = 1.6,
Bloodmoon = 1.58,
Lucky = 1.7,
Fire = 1.4,
Thunder = 1.5,
Starfall = 1.3,
Aurora = 2.2,
Radioactive = 2,
Poison = 1.5,
Wet = 1
}
--// =========================================================
--// ELIMINAR UI ANTERIOR
--// =========================================================
if PlayerGui:FindFirstChild("CrystalFinder") then
PlayerGui.CrystalFinder:Destroy()
end
--// =========================================================
--// SCREEN GUI
--// =========================================================
local ScreenGui = Instance.new("ScreenGui")
ScreenGui.Name = "CrystalFinder"
ScreenGui.ResetOnSpawn = false
ScreenGui.Parent = PlayerGui
--// =========================================================
--// MAIN
--// =========================================================
local Main = Instance.new("Frame")
Main.Name = "Main"
Main.Size = UDim2.new(0, 550, 0, 620)
Main.Position = UDim2.new(0.5, -275, 0.5, -310)
Main.BackgroundColor3 =
Color3.fromRGB(25, 25, 25)
Main.BorderSizePixel = 0
Main.Parent = ScreenGui
local MainCorner = Instance.new("UICorner")
MainCorner.CornerRadius =
UDim.new(0, 10)
MainCorner.Parent = Main
--// =========================================================
--// TITLE BAR
--// =========================================================
local TitleBar = Instance.new("Frame")
TitleBar.Size =
UDim2.new(1, 0, 0, 40)
TitleBar.BackgroundColor3 =
Color3.fromRGB(35, 35, 35)
TitleBar.BorderSizePixel = 0
TitleBar.Parent = Main
local Title = Instance.new("TextLabel")
Title.Size =
UDim2.new(1, -50, 1, 0)
Title.Position =
UDim2.new(0, 15, 0, 0)
Title.BackgroundTransparency = 1
Title.Text =
"💎 Crystal Finder"
Title.TextColor3 =
Color3.new(1, 1, 1)
Title.TextSize = 18
Title.Font = Enum.Font.GothamBold
Title.TextXAlignment =
Enum.TextXAlignment.Left
Title.Parent = TitleBar
--// =========================================================
--// CLOSE
--// =========================================================
local Close = Instance.new("TextButton")
Close.Size =
UDim2.new(0, 35, 0, 30)
Close.Position =
UDim2.new(1, -40, 0, 5)
Close.BackgroundColor3 =
Color3.fromRGB(180, 50, 50)
Close.BorderSizePixel = 0
Close.Text = "X"
Close.TextColor3 =
Color3.new(1, 1, 1)
Close.TextSize = 16
Close.Font = Enum.Font.GothamBold
Close.Parent = TitleBar
local CloseCorner = Instance.new("UICorner")
CloseCorner.CornerRadius =
UDim.new(0, 6)
CloseCorner.Parent = Close
Close.MouseButton1Click:Connect(function()
ScreenGui:Destroy()
end)
--// =========================================================
--// DRAG
--// =========================================================
local dragging = false
local dragStart
local startPos
TitleBar.InputBegan:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
dragging = true
dragStart = input.Position
startPos = Main.Position
end
end)
TitleBar.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
dragging = false
end
end)
UserInputService.InputChanged:Connect(function(input)
if dragging
and input.UserInputType ==
Enum.UserInputType.MouseMovement then
local delta =
input.Position - dragStart
Main.Position =
UDim2.new(
startPos.X.Scale,
startPos.X.Offset + delta.X,
startPos.Y.Scale,
startPos.Y.Offset + delta.Y
)
end
end)
--// =========================================================
--// FILTER BAR
--// =========================================================
local FilterBar = Instance.new("Frame")
FilterBar.Size =
UDim2.new(1, -20, 0, 80)
FilterBar.Position =
UDim2.new(0, 10, 0, 45)
FilterBar.BackgroundColor3 =
Color3.fromRGB(35, 35, 35)
FilterBar.BorderSizePixel = 0
FilterBar.Parent = Main
local FilterCorner = Instance.new("UICorner")
FilterCorner.CornerRadius =
UDim.new(0, 7)
FilterCorner.Parent = FilterBar
--// =========================================================
--// PESO LABEL
--// =========================================================
local WeightLabel = Instance.new("TextLabel")
WeightLabel.Size =
UDim2.new(0, 100, 0, 30)
WeightLabel.Position =
UDim2.new(0, 10, 0, 8)
WeightLabel.BackgroundTransparency = 1
WeightLabel.Text =
"⚖️ Peso máx:"
WeightLabel.TextColor3 =
Color3.new(1, 1, 1)
WeightLabel.TextSize = 14
WeightLabel.Font = Enum.Font.Gotham
WeightLabel.TextXAlignment =
Enum.TextXAlignment.Left
WeightLabel.Parent = FilterBar
--// =========================================================
--// PESO BOX
--// =========================================================
local WeightBox = Instance.new("TextBox")
WeightBox.Size =
UDim2.new(0, 120, 0, 30)
WeightBox.Position =
UDim2.new(0, 110, 0, 8)
WeightBox.BackgroundColor3 =
Color3.fromRGB(50, 50, 50)
WeightBox.BorderSizePixel = 0
WeightBox.PlaceholderText =
"Sin límite"
WeightBox.Text = ""
WeightBox.TextColor3 =
Color3.new(1, 1, 1)
WeightBox.PlaceholderColor3 =
Color3.fromRGB(150, 150, 150)
WeightBox.TextSize = 14
WeightBox.Font = Enum.Font.Gotham
WeightBox.ClearTextOnFocus = false
WeightBox.Parent = FilterBar
local WeightCorner = Instance.new("UICorner")
WeightCorner.CornerRadius =
UDim.new(0, 6)
WeightCorner.Parent = WeightBox
--// =========================================================
--// ORDEN LABEL
--// =========================================================
local SortLabel = Instance.new("TextLabel")
SortLabel.Size =
UDim2.new(0, 65, 0, 30)
SortLabel.Position =
UDim2.new(0, 245, 0, 8)
SortLabel.BackgroundTransparency = 1
SortLabel.Text = "Orden:"
SortLabel.TextColor3 =
Color3.new(1, 1, 1)
SortLabel.TextSize = 14
SortLabel.Font = Enum.Font.Gotham
SortLabel.TextXAlignment =
Enum.TextXAlignment.Left
SortLabel.Parent = FilterBar
--// =========================================================
--// ORDEN BUTTON
--// =========================================================
local SortButton = Instance.new("TextButton")
SortButton.Size =
UDim2.new(0, 120, 0, 30)
SortButton.Position =
UDim2.new(0, 315, 0, 8)
SortButton.BackgroundColor3 =
Color3.fromRGB(70, 100, 180)
SortButton.BorderSizePixel = 0
SortButton.Text =
"💰 Precio"
SortButton.TextColor3 =
Color3.new(1, 1, 1)
SortButton.TextSize = 13
SortButton.Font = Enum.Font.GothamBold
SortButton.Parent = FilterBar
local SortCorner = Instance.new("UICorner")
SortCorner.CornerRadius =
UDim.new(0, 6)
SortCorner.Parent = SortButton
--// =========================================================
--// SELECTOR CRISTALES / BETAS / RUNAS
--// =========================================================
local TypeButton = Instance.new("TextButton")
TypeButton.Name =
"TypeSelector"
TypeButton.Size =
UDim2.new(0, 120, 0, 30)
TypeButton.Position =
UDim2.new(0, 10, 0, 45)
TypeButton.BackgroundColor3 =
Color3.fromRGB(70, 100, 180)
TypeButton.BorderSizePixel = 0
TypeButton.Text =
"💎 Cristales"
TypeButton.TextColor3 =
Color3.new(1, 1, 1)
TypeButton.TextSize = 13
TypeButton.Font = Enum.Font.GothamBold
TypeButton.Parent = FilterBar
local TypeCorner = Instance.new("UICorner")
TypeCorner.CornerRadius =
UDim.new(0, 6)
TypeCorner.Parent = TypeButton
--// =========================================================
--// APPLY
--// =========================================================
local ApplyButton = Instance.new("TextButton")
ApplyButton.Size =
UDim2.new(0, 120, 0, 30)
ApplyButton.Position =
UDim2.new(0, 140, 0, 45)
ApplyButton.BackgroundColor3 =
Color3.fromRGB(60, 130, 80)
ApplyButton.BorderSizePixel = 0
ApplyButton.Text =
"Aplicar filtro"
ApplyButton.TextColor3 =
Color3.new(1, 1, 1)
ApplyButton.TextSize = 13
ApplyButton.Font = Enum.Font.GothamBold
ApplyButton.Parent = FilterBar
local ApplyCorner = Instance.new("UICorner")
ApplyCorner.CornerRadius =
UDim.new(0, 6)
ApplyCorner.Parent = ApplyButton
--// =========================================================
--// BOTÓN INTERACCIÓN INSTANTÁNEA
--// =========================================================
local InstantButton = Instance.new("TextButton")
InstantButton.Name =
"InstantInteractButton"
InstantButton.Size =
UDim2.new(0, 180, 0, 30)
InstantButton.Position =
UDim2.new(0, 270, 0, 45)
InstantButton.BackgroundColor3 =
Color3.fromRGB(90, 70, 70)
InstantButton.BorderSizePixel = 0
InstantButton.Text =
"⚡ Instantáneo: OFF"
InstantButton.TextColor3 =
Color3.new(1, 1, 1)
InstantButton.TextSize = 13
InstantButton.Font = Enum.Font.GothamBold
InstantButton.Parent = FilterBar
local InstantCorner = Instance.new("UICorner")
InstantCorner.CornerRadius =
UDim.new(0, 6)
InstantCorner.Parent = InstantButton
InstantButton.MouseButton1Click:Connect(function()
SetInstantInteract(
not InstantInteract
)
if InstantInteract then
InstantButton.Text =
"⚡ Instantáneo: ON"
InstantButton.BackgroundColor3 =
Color3.fromRGB(60, 140, 80)
else
InstantButton.Text =
"⚡ Instantáneo: OFF"
InstantButton.BackgroundColor3 =
Color3.fromRGB(90, 70, 70)
end
end)
--// =========================================================
--// SCROLL
--// =========================================================
local Scroll = Instance.new("ScrollingFrame")
Scroll.Name =
"CrystalList"
Scroll.Size =
UDim2.new(1, -20, 1, -135)
Scroll.Position =
UDim2.new(0, 10, 0, 135)
Scroll.BackgroundColor3 =
Color3.fromRGB(20, 20, 20)
Scroll.BorderSizePixel = 0
Scroll.ScrollBarThickness = 6
Scroll.CanvasSize =
UDim2.new(0, 0, 0, 0)
Scroll.ScrollingDirection =
Enum.ScrollingDirection.Y
Scroll.Parent = Main
local ScrollCorner = Instance.new("UICorner")
ScrollCorner.CornerRadius =
UDim.new(0, 8)
ScrollCorner.Parent = Scroll
--// =========================================================
--// CACHE
--// =========================================================
local CrystalCache = {}
--// =========================================================
--// OBTENER TEXTO
--// =========================================================
local function GetCrystalText(crystal)
local cached =
CrystalCache[crystal]
if cached
and cached.Text then
return cached.Text
end
local text = ""
for _, obj in ipairs(
crystal:GetDescendants()
) do
if obj:IsA("ProximityPrompt") then
if obj.ObjectText then
text =
text
.. " "
.. obj.ObjectText
end
if obj.ActionText then
text =
text
.. " "
.. obj.ActionText
end
if text ~= "" then
break
end
end
end
CrystalCache[crystal] =
CrystalCache[crystal] or {}
CrystalCache[crystal].Text =
text
return text
end
--// =========================================================
--// NOMBRE
--// =========================================================
local function GetCrystalName(crystal)
local cached =
CrystalCache[crystal]
if cached
and cached.Name then
return cached.Name
end
local text =
GetCrystalText(
crystal
)
text =
text:match("^%s*(.-)%s*$")
or ""
local name =
text:match(
"^%s*%[[^%]]+%]%s*(.-)%s*%.%s*[%d%.,]+%s*[Kk][Gg]%s*%."
)
if not name
or name == "" then
name =
crystal.Name
end
CrystalCache[crystal] =
CrystalCache[crystal] or {}
CrystalCache[crystal].Name =
name
return name
end
--// =========================================================
--// PESO
--// =========================================================
local function GetCrystalWeight(crystal)
local cached =
CrystalCache[crystal]
if cached
and cached.Weight ~= nil then
return cached.Weight
end
local text =
GetCrystalText(
crystal
)
local weightText =
text:match(
"([%d%.,]+)%s*[Kk][Gg]"
)
local weight = 0
if weightText then
weightText =
weightText:gsub(
",",
"."
)
weight =
tonumber(weightText)
or 0
end
if weight == 0 then
local attributes = {
"WeightKg",
"LuckKg",
"Weight",
"Peso",
"CrystalWeight"
}
for _, attribute in ipairs(
attributes
) do
local value =
crystal:GetAttribute(
attribute
)
if typeof(value) ==
"number" then
weight = value
break
end
end
end
CrystalCache[crystal] =
CrystalCache[crystal] or {}
CrystalCache[crystal].Weight =
weight
return weight
end
--// =========================================================
--// PRECIO
--// =========================================================
local function GetCrystalPrice(crystal)
local cached =
CrystalCache[crystal]
if cached
and cached.Price ~= nil then
return cached.Price
end
local text =
GetCrystalText(
crystal
)
local priceText =
text:match(
"%$([%d,]+)"
)
local price = 0
if priceText then
priceText =
priceText:gsub(
",",
""
)
price =
tonumber(priceText)
or 0
end
if price == 0 then
local attributes = {
"Price",
"Value",
"SellPrice",
"Cash",
"Money",
"Cost"
}
for _, attribute in ipairs(
attributes
) do
local value =
crystal:GetAttribute(
attribute
)
if typeof(value) ==
"number" then
price = value
break
end
end
end
CrystalCache[crystal] =
CrystalCache[crystal] or {}
CrystalCache[crystal].Price =
price
return price
end
--// =========================================================
--// RAREZA DE BETAS
--// =========================================================
local RarityOrder = {
Legendary = 3,
Epic = 2,
Rare = 1
}
local function GetBoulderRarity(boulder)
local rarity =
boulder:GetAttribute(
"Rarity"
)
if typeof(rarity) == "string" then
return rarity
end
return "Unknown"
end
--// =========================================================
--// MUTACIONES
--// =========================================================
local function GetMutationMultiplier(
mutations
)
if type(mutations) ~= "string"
or mutations == "" then
return 1
end
local multiplier = 1
for mutationName in string.gmatch(
mutations,
"[^,]+"
) do
mutationName =
mutationName:gsub(
"^%s+",
""
):gsub(
"%s+$",
""
)
local value =
MutationLuck[
mutationName
]
if value then
multiplier *= value
end
end
return multiplier
end
--// =========================================================
--// SUERTE
--// =========================================================
local function GetCrystalLuck(crystal)
local cached =
CrystalCache[crystal]
if cached
and cached.Luck ~= nil then
return cached.Luck
end
local tier =
tonumber(
crystal:GetAttribute(
"Tier"
)
) or 1
local rarity =
RarityMult[tier]
or RarityMult[1]
local weight =
crystal:GetAttribute(
"LuckKg"
)
if typeof(weight) ~= "number" then
weight =
crystal:GetAttribute(
"WeightKg"
)
end
if typeof(weight) ~= "number" then
weight =
GetCrystalWeight(
crystal
)
end
weight =
tonumber(weight)
or 0
local luck =
rarity
* math.min(
math.max(
0,
weight
),
KgCap
) ^ WeightExp
* Base
if crystal:GetAttribute(
"BombCrystal"
) == true then
luck *= BombCrystalMult
end
local mutation =
crystal:GetAttribute(
"Mutation"
)
local mutationLuckRoll =
crystal:GetAttribute(
"MutationLuckRoll"
)
local multiplier
if typeof(mutationLuckRoll)
== "number"
and mutationLuckRoll > 0 then
multiplier =
mutationLuckRoll
else
multiplier =
GetMutationMultiplier(
mutation
)
end
local extra =
crystal:GetAttribute(
"ExtraMutations"
)
if type(extra) == "string"
and extra ~= "" then
multiplier *=
GetMutationMultiplier(
extra
)
end
if crystal:GetAttribute(
"IsBloodCrystal"
) == true then
multiplier *= BloodLuckMult
end
local adminMutation =
crystal:GetAttribute(
"AdminMutation"
)
if adminMutation ==
"Radioactive"
and mutation ~=
"Radioactive" then
local hasRadioactive = false
if type(extra) ==
"string" then
hasRadioactive =
extra:find(
"Radioactive",
1,
true
) ~= nil
end
if not hasRadioactive then
multiplier *=
MutationLuck.Radioactive
end
end
luck *= multiplier
CrystalCache[crystal] =
CrystalCache[crystal] or {}
CrystalCache[crystal].Luck =
luck
return luck
end
--// =========================================================
--// FORMATO PRECIO
--// =========================================================
local function FormatPrice(price)
local formatted =
tostring(
math.floor(price)
)
while true do
local newFormatted, count =
formatted:gsub(
"^(-?%d+)(%d%d%d)",
"%1,%2"
)
formatted =
newFormatted
if count == 0 then
break
end
end
return "$" .. formatted
end
--// =========================================================
--// FORMATO SUERTE
--// =========================================================
local LuckSuffixes = {
"M",
"B",
"T",
"Qa",
"Qi",
"Sx",
"Sp",
"Oc",
"No",
"Dc"
}
local function FormatLuck(luck)
local percent =
luck * 100
if percent == 0 then
return "+0%"
end
if percent < 1 then
return string.format(
"+%.2f%%",
percent
)
end
if percent < 10 then
return string.format(
"+%.1f%%",
percent
)
end
if percent < 1000000 then
local formatted =
tostring(
math.floor(
percent + 0.5
)
)
while true do
local newFormatted, count =
formatted:gsub(
"^(%d+)(%d%d%d)",
"%1,%2"
)
formatted =
newFormatted
if count == 0 then
break
end
end
return "+" ..
formatted ..
"%"
end
local count =
math.min(
math.floor(
math.log(
percent,
1000
)
) - 1,
#LuckSuffixes
)
if count < 1 then
count = 1
end
local value =
percent /
1000 ^ (count + 1)
if value >= 999.995
and count <
#LuckSuffixes then
count += 1
value =
percent /
1000 ^ (count + 1)
end
return string.format(
"+%.2f%s%%",
value,
LuckSuffixes[count]
)
end
--// =========================================================
--// PESO MÁXIMO
--// =========================================================
local function GetMaxWeight()
local text =
WeightBox.Text
if text == "" then
return nil
end
text =
text:gsub(
",",
"."
)
local numberText =
text:match(
"[%d%.]+"
)
if not numberText then
return nil
end
return tonumber(numberText)
end
--// =========================================================
--// ORDEN
--// =========================================================
local SortMode = "Price"
--// =========================================================
--// LISTA
--// =========================================================
local CrystalList = {}
--// =========================================================
--// TOKEN
--// =========================================================
local LoadToken = 0
--// =========================================================
--// CREAR ITEM VIRTUALIZADO
--// =========================================================
local function CreateVirtualItem()
local item = Instance.new("Frame")
item.Size =
UDim2.new(
1,
-12,
0,
ITEM_HEIGHT
)
item.BackgroundColor3 =
Color3.fromRGB(
35,
35,
35
)
item.BorderSizePixel = 0
item.Visible = false
item.Parent = Scroll
local corner =
Instance.new("UICorner")
corner.CornerRadius =
UDim.new(0, 7)
corner.Parent = item
--// NOMBRE
local NameLabel =
Instance.new("TextLabel")
NameLabel.Size =
UDim2.new(
0.58,
0,
0,
24
)
NameLabel.Position =
UDim2.new(
0,
10,
0,
4
)
NameLabel.BackgroundTransparency = 1
NameLabel.TextColor3 =
Color3.new(1, 1, 1)
NameLabel.TextSize = 14
NameLabel.Font =
Enum.Font.GothamBold
NameLabel.TextXAlignment =
Enum.TextXAlignment.Left
NameLabel.TextTruncate =
Enum.TextTruncate.AtEnd
NameLabel.Parent = item
--// PRECIO / RAREZA
local PriceLabel =
Instance.new("TextLabel")
PriceLabel.Size =
UDim2.new(
0.30,
0,
0,
20
)
PriceLabel.Position =
UDim2.new(
0,
10,
0,
28
)
PriceLabel.BackgroundTransparency = 1
PriceLabel.TextColor3 =
Color3.fromRGB(
100,
255,
120
)
PriceLabel.TextSize = 13
PriceLabel.Font =
Enum.Font.GothamBold
PriceLabel.TextXAlignment =
Enum.TextXAlignment.Left
PriceLabel.Parent = item
--// SUERTE
local LuckLabel =
Instance.new("TextLabel")
LuckLabel.Size =
UDim2.new(
0.28,
0,
0,
20
)
LuckLabel.Position =
UDim2.new(
0.30,
0,
0,
28
)
LuckLabel.BackgroundTransparency = 1
LuckLabel.TextColor3 =
Color3.fromRGB(
120,
255,
140
)
LuckLabel.TextSize = 12
LuckLabel.Font =
Enum.Font.GothamBold
LuckLabel.TextXAlignment =
Enum.TextXAlignment.Left
LuckLabel.Parent = item
--// PESO
local WeightLabelItem =
Instance.new("TextLabel")
WeightLabelItem.Size =
UDim2.new(
0.30,
0,
0,
20
)
WeightLabelItem.Position =
UDim2.new(
0,
10,
0,
50
)
WeightLabelItem.BackgroundTransparency = 1
WeightLabelItem.TextColor3 =
Color3.fromRGB(
180,
180,
255
)
WeightLabelItem.TextSize = 12
WeightLabelItem.Font =
Enum.Font.Gotham
WeightLabelItem.TextXAlignment =
Enum.TextXAlignment.Left
WeightLabelItem.Parent = item
--// POSICIÓN
local PositionLabel =
Instance.new("TextLabel")
PositionLabel.Size =
UDim2.new(
0.35,
0,
0,
20
)
PositionLabel.Position =
UDim2.new(
0.58,
0,
0,
50
)
PositionLabel.BackgroundTransparency = 1
PositionLabel.TextColor3 =
Color3.fromRGB(
180,
180,
180
)
PositionLabel.TextSize = 10
PositionLabel.Font =
Enum.Font.Gotham
PositionLabel.TextXAlignment =
Enum.TextXAlignment.Left
PositionLabel.TextTruncate =
Enum.TextTruncate.AtEnd
PositionLabel.Parent = item
--// TP
local TeleportButton =
Instance.new("TextButton")
TeleportButton.Size =
UDim2.new(
0,
65,
0,
32
)
TeleportButton.Position =
UDim2.new(
1,
-75,
0.5,
-16
)
TeleportButton.BackgroundColor3 =
Color3.fromRGB(
70,
100,
180
)
TeleportButton.BorderSizePixel = 0
TeleportButton.Text = "TP"
TeleportButton.TextColor3 =
Color3.new(1, 1, 1)
TeleportButton.TextSize = 14
TeleportButton.Font =
Enum.Font.GothamBold
TeleportButton.Parent = item
local TpCorner =
Instance.new("UICorner")
TpCorner.CornerRadius =
UDim.new(0, 6)
TpCorner.Parent =
TeleportButton
--// REFERENCIA ACTUAL
local currentCrystal = nil
TeleportButton.MouseButton1Click:Connect(function()
local crystal =
currentCrystal
if not crystal then
return
end
if not crystal.Parent then
return
end
local character =
Player.Character
local root =
character
and character:FindFirstChild(
"HumanoidRootPart"
)
local targetPart
if crystal:IsA("BasePart") then
targetPart = crystal
else
targetPart =
crystal:FindFirstChildWhichIsA(
"BasePart",
true
)
end
if root
and targetPart
and targetPart.Parent then
root.CFrame =
targetPart.CFrame
+ Vector3.new(
0,
3,
0
)
end
end)
--// ACTUALIZAR ITEM
local function SetCrystal(crystal)
currentCrystal =
crystal
if not crystal then
item.Visible = false
return
end
local name =
GetCrystalName(
crystal
)
local weight =
GetCrystalWeight(
crystal
)
if CurrentType ==
"Boulders" then
local rarity =
GetBoulderRarity(
crystal
)
NameLabel.Text =
"🪨 " .. name
PriceLabel.Text =
"⭐ " .. rarity
LuckLabel.Text =
""
elseif CurrentType ==
"Runes" then
NameLabel.Text =
"🔮 " .. name
PriceLabel.Text =
""
LuckLabel.Text =
""
else
local price =
GetCrystalPrice(
crystal
)
local luck =
GetCrystalLuck(
crystal
)
NameLabel.Text =
"💎 " .. name
PriceLabel.Text =
"💰 " ..
FormatPrice(price)
LuckLabel.Text =
"🍀 " ..
FormatLuck(luck)
end
WeightLabelItem.Text =
"⚖️ " ..
string.format(
"%.2fkg",
weight
)
local part
if crystal:IsA("BasePart") then
part = crystal
else
part =
crystal:FindFirstChildWhichIsA(
"BasePart",
true
)
end
if part then
local pos =
part.Position
PositionLabel.Text =
string.format(
"📍 %.0f, %.0f, %.0f",
pos.X,
pos.Y,
pos.Z
)
else
PositionLabel.Text =
"📍 ?"
end
item.Visible = true
end
return {
Frame = item,
SetCrystal = SetCrystal
}
end
--// =========================================================
--// POOL
--// =========================================================
local VirtualItems = {}
local function GetRequiredPoolSize()
local viewportHeight =
Scroll.AbsoluteWindowSize.Y
if viewportHeight <= 0 then
viewportHeight = 450
end
local visibleRows =
math.ceil(
viewportHeight /
(
ITEM_HEIGHT
+ ITEM_PADDING
)
)
return visibleRows + EXTRA_ROWS
end
local function EnsurePool()
local required =
GetRequiredPoolSize()
while #VirtualItems <
required do
table.insert(
VirtualItems,
CreateVirtualItem()
)
end
end
--// =========================================================
--// ACTUALIZAR LISTA VIRTUAL
--// =========================================================
local UpdatingVirtual = false
local function UpdateVirtualList()
if UpdatingVirtual then
return
end
UpdatingVirtual = true
EnsurePool()
local total =
#CrystalList
if total == 0 then
for _, virtual in ipairs(
VirtualItems
) do
virtual.SetCrystal(nil)
end
UpdatingVirtual = false
return
end
local rowHeight =
ITEM_HEIGHT + ITEM_PADDING
local canvasY =
Scroll.CanvasPosition.Y
local firstIndex =
math.floor(
canvasY / rowHeight
) + 1
firstIndex =
math.max(
1,
firstIndex - 2
)
local poolSize =
#VirtualItems
for poolIndex = 1, poolSize do
local crystalIndex =
firstIndex
+ poolIndex
- 1
local virtual =
VirtualItems[poolIndex]
if crystalIndex <= total then
local crystal =
CrystalList[
crystalIndex
]
virtual.Frame.Position =
UDim2.new(
0,
0,
0,
(
crystalIndex - 1
) * rowHeight
)
virtual.SetCrystal(
crystal
)
else
virtual.SetCrystal(nil)
end
end
UpdatingVirtual = false
end
--// =========================================================
--// SCROLL
--// =========================================================
Scroll:GetPropertyChangedSignal(
"CanvasPosition"
):Connect(function()
UpdateVirtualList()
end)
--// =========================================================
--// CAMBIO TAMAÑO
--// =========================================================
Scroll:GetPropertyChangedSignal(
"AbsoluteWindowSize"
):Connect(function()
EnsurePool()
UpdateVirtualList()
end)
--// =========================================================
--// OBTENER TODOS LOS CRISTALES (CON PROTECCIÓN)
--// =========================================================
local function GetAllCrystals()
local allCrystals = {}
-- Cristales de Things.Crystals
for _, crystal in ipairs(
CrystalsFolder:GetChildren()
) do
table.insert(allCrystals, crystal)
end
-- Cristales de DroppedCrystals (si existe)
if DroppedCrystalsFolder then
for _, crystal in ipairs(
DroppedCrystalsFolder:GetChildren()
) do
table.insert(allCrystals, crystal)
end
end
return allCrystals
end
--// =========================================================
--// OBTENER TODAS LAS RUNAS (CON PROTECCIÓN)
--// =========================================================
local function GetAllRunes()
local allRunes = {}
if DroppedRunesFolder then
for _, rune in ipairs(
DroppedRunesFolder:GetChildren()
) do
table.insert(allRunes, rune)
end
end
return allRunes
end
--// =========================================================
--// ACTUALIZAR LISTA
--// =========================================================
local function UpdateCrystalList()
LoadToken += 1
local CurrentToken =
LoadToken
if CurrentType ==
"Boulders" then
Title.Text =
"🪨 Analizando betas..."
elseif CurrentType ==
"Runes" then
Title.Text =
"🔮 Analizando runas..."
else
Title.Text =
"💎 Analizando cristales..."
end
--// =============================================
--// OBTENER OBJETOS
--// =============================================
local allCrystals = {}
if CurrentType ==
"Boulders" then
for _, crystal in ipairs(
BouldersFolder:GetChildren()
) do
table.insert(
allCrystals,
crystal
)
end
elseif CurrentType ==
"Runes" then
allCrystals = GetAllRunes()
else
allCrystals = GetAllCrystals()
end
--// =============================================
--// FILTRO
--// =============================================
local maxWeight =
GetMaxWeight()
local filtered = {}
for i, crystal in ipairs(
allCrystals
) do
if CurrentToken ~=
LoadToken then
return
end
local weight =
GetCrystalWeight(
crystal
)
if maxWeight == nil then
table.insert(
filtered,
crystal
)
elseif weight > 0
and weight <= maxWeight then
table.insert(
filtered,
crystal
)
end
if i % 150 == 0 then
if CurrentType ==
"Boulders" then
Title.Text =
string.format(
"🪨 Analizando... %d/%d",
i,
#allCrystals
)
elseif CurrentType ==
"Runes" then
Title.Text =
string.format(
"🔮 Analizando... %d/%d",
i,
#allCrystals
)
else
Title.Text =
string.format(
"💎 Analizando... %d/%d",
i,
#allCrystals
)
end
task.wait()
end
end
if CurrentToken ~=
LoadToken then
return
end
--// =============================================
--// ORDENAR
--// =============================================
if CurrentType ==
"Boulders" then
-- ==========================================
-- BETAS:
-- Legendary
-- Epic
-- Rare
-- ==========================================
table.sort(
filtered,
function(a, b)
local rarityA =
GetBoulderRarity(a)
local rarityB =
GetBoulderRarity(b)
local orderA =
RarityOrder[rarityA]
or 0
local orderB =
RarityOrder[rarityB]
or 0
if orderA == orderB then
local weightA =
GetCrystalWeight(a)
local weightB =
GetCrystalWeight(b)
if weightA == weightB then
return GetCrystalName(a)
< GetCrystalName(b)
end
return weightA > weightB
end
return orderA > orderB
end
)
elseif CurrentType ==
"Runes" then
-- ==========================================
-- RUNAS: Ordenar por peso (más pesado primero)
-- ==========================================
table.sort(
filtered,
function(a, b)
local weightA =
GetCrystalWeight(a)
local weightB =
GetCrystalWeight(b)
if weightA == weightB then
return GetCrystalName(a)
< GetCrystalName(b)
end
return weightA > weightB
end
)
elseif SortMode ==
"Price" then
-- ==========================================
-- CRISTALES: PRECIO
-- ==========================================
table.sort(
filtered,
function(a, b)
local priceA =
GetCrystalPrice(a)
local priceB =
GetCrystalPrice(b)
if priceA == priceB then
return GetCrystalLuck(a)
> GetCrystalLuck(b)
end
return priceA > priceB
end
)
else
-- ==========================================
-- CRISTALES: SUERTE
-- ==========================================
table.sort(
filtered,
function(a, b)
local luckA =
GetCrystalLuck(a)
local luckB =
GetCrystalLuck(b)
if luckA == luckB then
return GetCrystalPrice(a)
> GetCrystalPrice(b)
end
return luckA > luckB
end
)
end
if CurrentToken ~=
LoadToken then
return
end
CrystalList =
filtered
--// =============================================
--// CANVAS
--// =============================================
local total =
#CrystalList
local rowHeight =
ITEM_HEIGHT + ITEM_PADDING
local canvasHeight =
math.max(
0,
total * rowHeight
)
Scroll.CanvasSize =
UDim2.new(
0,
0,
0,
canvasHeight
)
EnsurePool()
UpdateVirtualList()
--// =============================================
--// TÍTULO
--// =============================================
local sortText
if CurrentType ==
"Boulders" then
sortText =
"⭐ Rareza"
elseif CurrentType ==
"Runes" then
sortText =
"⚖️ Peso"
elseif SortMode ==
"Price" then
sortText =
"💰 Precio"
else
sortText =
"🍀 Suerte"
end
local icon
if CurrentType ==
"Boulders" then
icon = "🪨"
elseif CurrentType ==
"Runes" then
icon = "🔮"
else
icon = "💎"
end
if maxWeight then
Title.Text =
string.format(
"%s %s | ≤ %.2fkg | %d",
icon,
sortText,
maxWeight,
total
)
else
if CurrentType ==
"Boulders" then
Title.Text =
string.format(
"🪨 %s | %d betas",
sortText,
total
)
elseif CurrentType ==
"Runes" then
Title.Text =
string.format(
"🔮 %s | %d runas",
sortText,
total
)
else
Title.Text =
string.format(
"💎 %s | %d cristales",
sortText,
total
)
end
end
end
--// =========================================================
--// CAMBIAR CRISTALES / BETAS / RUNAS
--// =========================================================
TypeButton.MouseButton1Click:Connect(function()
if CurrentType ==
"Crystals" then
CurrentType =
"Boulders"
TypeButton.Text =
"🪨 Betas"
TypeButton.BackgroundColor3 =
Color3.fromRGB(
130,
100,
65
)
SortMode =
"Rarity"
SortButton.Text =
"⭐ Rareza"
elseif CurrentType ==
"Boulders" then
-- Verificar si existe la carpeta de runas antes de cambiar
if not DroppedRunesFolder then
-- Si no existe, volver a cristales
CurrentType = "Crystals"
TypeButton.Text = "💎 Cristales"
TypeButton.BackgroundColor3 = Color3.fromRGB(70, 100, 180)
SortMode = "Price"
SortButton.Text = "💰 Precio"
Scroll.CanvasPosition = Vector2.new(0, 0)
UpdateCrystalList()
return
end
CurrentType =
"Runes"
TypeButton.Text =
"🔮 Runas"
TypeButton.BackgroundColor3 =
Color3.fromRGB(
100,
70,
130
)
SortMode =
"Weight"
SortButton.Text =
"⚖️ Peso"
else
CurrentType =
"Crystals"
TypeButton.Text =
"💎 Cristales"
TypeButton.BackgroundColor3 =
Color3.fromRGB(
70,
100,
180
)
SortMode =
"Price"
SortButton.Text =
"💰 Precio"
end
Scroll.CanvasPosition =
Vector2.new(
0,
0
)
UpdateCrystalList()
end)
--// =========================================================
--// CAMBIAR PRECIO / SUERTE / RAREZA / PESO
--// =========================================================
SortButton.MouseButton1Click:Connect(function()
if CurrentType ==
"Boulders" then
SortMode =
"Rarity"
SortButton.Text =
"⭐ Rareza"
elseif CurrentType ==
"Runes" then
-- Las runas solo se ordenan por peso
SortMode =
"Weight"
SortButton.Text =
"⚖️ Peso"
else
if SortMode ==
"Price" then
SortMode =
"Luck"
SortButton.Text =
"🍀 Suerte"
else
SortMode =
"Price"
SortButton.Text =
"💰 Precio"
end
end
UpdateCrystalList()
end)
--// =========================================================
--// APLICAR FILTRO
--// =========================================================
ApplyButton.MouseButton1Click:Connect(function()
UpdateCrystalList()
end)
--// =========================================================
--// ENTER
--// =========================================================
WeightBox.FocusLost:Connect(function(
enterPressed
)
if enterPressed then
UpdateCrystalList()
end
end)
--// =========================================================
--// INICIALIZAR
--// =========================================================
EnsurePool()
task.spawn(function()
UpdateCrystalList()
end)
--// =========================================================
--// REFRESH AUTOMÁTICO
--// =========================================================
task.spawn(function()
while ScreenGui.Parent do
task.wait(
REFRESH_TIME
)
if ScreenGui.Parent then
UpdateCrystalList()
end
end
end)No comments yet for this script.


