opensource Tp, instant mine (no key) working again
Key Required

opensource Tp, instant mine (no key) working again

[⛰️] Mine a MountainYimitriYiYimitriYi 2.7K views 11.4K executesUpdated Sep 4, 2026
Unrated
00
Lua Script•2618 lines (50224 chars)
--[[
	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)

Features & Information

tp to crystals ordered by rarity/price tp to Veins

Community Comments (0)

No comments yet for this script.

More Scripts for [⛰️] Mine a Mountain