What's new
Heapleak - Scripthub

Get the most out of HeapLeak by creating a free account! Once signed in, you’ll gain full access to restricted content, be able to share your own scripts, and participate in our member-only discussions.

Grace Auto Farm Script

Version / Update: v1.0.0
Download / Script Link
--!nocheck
assert(game.PlaceId == 110333320616502, "This script is only for \"Grace\"")
local Library = loadstring(game:HttpGet("https://raw.githubusercontent.com/deividcomsono/Obsidian/refs/heads/main/Library.lua"))()

--// Main Logic //
local Speaker = game:GetService("Players").LocalPlayer
local RunService = game:GetService("RunService")
local Rooms = workspace:WaitForChild("Rooms")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Settings = {
CanStart = false,
Running = false,
NoEffects = false,
SkipSafeRooms = false,
ExitSafeRoom = false,
DebugLogs = false,
ProcessedRooms = {},
RemovedRemotes = {},
StuckDetection = 1,
LatestSuccess = os.clock(),
CurrentRoomNumber = 0,
AutoPlay = nil
}

local function DPrint(Text: string)
if Settings.DebugLogs then print(`[Grace Autoplay] {Text}`) end
end

local function DWarn(Text: string)
if Settings.DebugLogs then warn(`[Grace Autoplay] {Text}`) end
end

local function ResetProcessState()
Settings.ProcessedRooms = {}
Settings.CurrentRoomNumber = 0
Settings.LatestSuccess = os.clock()
DPrint("Processing state reset")
end

local function ProcessRoom(Room, RoomNumber)
local Character = Speaker.Character
if not Character then
DWarn("Cannot process room: Character does not exist")
return false
end

if RoomNumber > Settings.CurrentRoomNumber then
Settings.CurrentRoomNumber = RoomNumber
DPrint(`Updated current room number to {RoomNumber}`)
end

if Settings.ProcessedRooms[RoomNumber] then
DPrint(`Skipped processed room {RoomNumber}`)
return false
end

DPrint(`Start processing room {RoomNumber}`)
local Entrance = Room:WaitForChild("Entrance")
if not Entrance then
DWarn(`Room {RoomNumber} has no entrance point`)
return false
end
Character:PivotTo(Entrance.CFrame)
DPrint(`Moved character to room {RoomNumber} entrance`)

local Vault = Room:FindFirstChild("VaultEntrance")
local Prompt = Vault and Vault.Hinged.Cylinder:FindFirstChild("ProximityPrompt")
if not Settings.SkipSafeRooms and Prompt then
DPrint(`Safe room detected, triggering prompt`)
local Trigger = ReplicatedStorage:FindFirstChild("TriggerPrompt")
Trigger:FireServer(Prompt)
Character:PivotTo(Vault:GetPivot())

Settings.ExitSafeRoom = true
Settings.ProcessedRooms[RoomNumber] = true
DPrint(`Successfully entered safe room, waiting to exit`)
return true
elseif Settings.ExitSafeRoom then
DPrint("Exiting safe room")
Settings.ExitSafeRoom = false
local SafeRoom = Room:FindFirstChild("SafeRoom")
local Hitbox = SafeRoom and SafeRoom:FindFirstChild("hitbox")

if Hitbox then
DPrint("Found safe room exit, expanding hitbox")
Character:PivotTo(Hitbox.CFrame)
Hitbox.Size = Vector3.new(2048, 2048, 2048)
Hitbox.CFrame = Character:GetPivot()
else
DWarn("Safe room exit hitbox not found")
end
return true
end

local Plug = Room:FindFirstChild("Plug")
local Touch = Plug and Plug:FindFirstChild("plugTouch")
if Touch then
DPrint("Found plug, expanding trigger area")
Touch.Size = Vector3.new(2048, 2048, 2048)
Touch.CFrame = Character:GetPivot()
end

local Beacon = Room:FindFirstChild("Beacon")
local Hitbox = Beacon and Beacon:FindFirstChild("Hitbox")
if Hitbox then
DPrint("Found beacon, expanding hitbox")
Hitbox.Size = Vector3.new(2048, 2048, 2048)
Hitbox.CFrame = Character:GetPivot()
end

Settings.ProcessedRooms[RoomNumber] = true
DPrint(`Room {RoomNumber} processing complete`)
return true
end

local function GetRoomsByNumber()
local RoomsByNumber = {}
local RoomNumbers = {}

for _, Room in Rooms:GetChildren() do
local RoomNumber = tonumber(Room.Name)
if RoomNumber then
RoomsByNumber[RoomNumber] = Room
table.insert(RoomNumbers, RoomNumber)
end
end

table.sort(RoomNumbers)

return RoomsByNumber, RoomNumbers
end

local function CheckResetNeeded()
local _, RoomNumbers = GetRoomsByNumber()
if #RoomNumbers == 0 then
return false
end
local LastRoomNumber = math.max(unpack(RoomNumbers))

if LastRoomNumber < Settings.CurrentRoomNumber - 5 then
DPrint("Detected a significant drop in room number, resetting processing state")
ResetProcessState()
return true
end

local AllProcessed = true
for _, RoomNumber in RoomNumbers do
if not Settings.ProcessedRooms[RoomNumber] then
AllProcessed = false
break
end
end

if AllProcessed and #RoomNumbers > 0 then
local TimeSinceSuccess = os.clock() - Settings.LatestSuccess
if TimeSinceSuccess > Settings.StuckDetection * 2 then
DPrint("All rooms processed but character is stuck, resetting processing state")
ResetProcessState()
return true
end
end

return false
end

local function ProcessLatestRooms()
if not Settings.Running or not Settings.CanStart then return end

local Character = Speaker.Character
if not Character then return end

local RoomsByNumber, RoomNumbers = GetRoomsByNumber()
if #RoomNumbers == 0 then return end

local LastRoomNumber = math.max(unpack(RoomNumbers))
if Library.Labels.LastRoom then
Library.Labels.LastRoom:SetText(`Last Room: {LastRoomNumber}`)
end

CheckResetNeeded()

if Settings.ExitSafeRoom then
for RoomNumber, Room in RoomsByNumber do
if ProcessRoom(Room, RoomNumber) then
Settings.LatestSuccess = os.clock()
break
end
end
return
end

local Processed = false
for i = #RoomNumbers, 1, -1 do
local RoomNumber = RoomNumbers[i]
if not Settings.ProcessedRooms[RoomNumber] then
if ProcessRoom(RoomsByNumber[RoomNumber], RoomNumber) then
Settings.LatestSuccess = os.clock()
Processed = true
break
end
end
end

if not Processed and os.clock() - Settings.LatestSuccess > Settings.StuckDetection then
DWarn("Stuck detected, resetting processing state")
ResetProcessState()
end
end

Library:GiveSignal(Rooms.ChildAdded:Connect(function(Room)
if not Settings.Running then
DPrint("Autoplay is not enabled, ignoring new room")
return
end

local RoomNumber = tonumber(Room.Name)
if not RoomNumber then
DWarn(`Ignoring invalid room name: {Room.Name}`)
return
end

DPrint(`New room detected: {RoomNumber}, starting processing`)

if ProcessRoom(Room, RoomNumber) then
Settings.LatestSuccess = os.clock()
end
end))

Library:GiveSignal(Speaker.PlayerGui.ChildAdded:Connect(function(Child)
if Child.Name == "rushui" and Settings.NoEffects then
DPrint("Disabling rushui effect")
end
Child.Enabled = Child.Enabled and not (Child.Name == "rushui" and Settings.NoEffects)
end))

--// UI Elements //
local Window = Library:CreateWindow({
ShowCustomCursor = false,
Title = "mspaint",
Footer = "Game: Grace | Build 9.9.9.9",
Icon = 95816097006870,
Font = Enum.Font.Gotham
})
local Tab = Window:AddTab("Main", "home")
local Groupbox = Tab:AddLeftGroupbox("Grace Autoplay")

Groupbox:AddLabel("LastRoom", {
Text = "Last Room: 3"
})

Groupbox:AddButton("TP to Last Room", function()
local Character = Speaker.Character
if not Character then
DWarn("Cannot teleport to the last room: Character does not exist")
return
end

if Settings.Running then
DWarn("Cannot teleport to the last room: Autoplay is running")
return
end

local RoomsByNumber, RoomNumbers = GetRoomsByNumber()
if #RoomNumbers == 0 then
DWarn("Cannot teleport: No rooms available")
return
end

local LastRoomNumber = math.max(unpack(RoomNumbers))
local LastRoom = RoomsByNumber[LastRoomNumber]

local function TPed(CFrame)
Character:PivotTo(CFrame)
DPrint(`Successfully teleported to room {LastRoomNumber + 1}`)
Library.Labels.LastRoom:SetText(`Last Room: {LastRoomNumber + 1}`)
end

if not LastRoom then
DWarn(`Cannot find room {LastRoomNumber}`)
return
end

DPrint(`Teleporting to room {LastRoomNumber}`)

local Entrance = LastRoom:FindFirstChild("Entrance")
if Entrance then
TPed(Entrance.CFrame)
return
end

local SafeRoom = LastRoom:FindFirstChild("SafeRoom")
if SafeRoom then
local Scale = SafeRoom:FindFirstChild("Scale")
if Scale then
TPed(Scale:GetPivot())
return
end

local Hitbox = SafeRoom:FindFirstChild("hitbox")
if Hitbox then
TPed(Hitbox.CFrame)
return
end

TPed(SafeRoom:GetPivot())
return
end

local Beacon = LastRoom:FindFirstChild("Beacon")
if Beacon then
TPed(Beacon:GetPivot())
return
end

local Plug = LastRoom:FindFirstChild("Plug")
if Plug then
TPed(Plug:GetPivot())
return
end
end)

Groupbox:AddDivider()

Settings.AutoPlay = Groupbox:AddToggle("Autoplay", {
Text = "Autoplay",
Changed = function(Enabled)
if not Settings.CanStart then return end
Settings.Running = Enabled
DPrint(`Autoplay has been {Enabled and "enabled" or "disabled"}`)
if Enabled then
ResetProcessState()
end
end
})

Groupbox:AddToggle("SkipSafeRooms", {
Text = "Skip Safe Rooms",
Changed = function(Enabled)
Settings.SkipSafeRooms = Enabled
DPrint(`Skip Safe Rooms has been {Enabled and "enabled" or "disabled"}`)
end
})

Groupbox:AddToggle("NoEffects",{
Text = "No Effects",
Changed = function(Enabled)
Settings.NoEffects = Enabled
DPrint(`No Effects has been {Enabled and "enabled" or "disabled"}`)
Speaker.PlayerGui.effect.Enabled = not Enabled
end
})

Groupbox:AddToggle("NoEntities", {
Text = "No Entities (Anti-Lag)",
Changed = function(Enabled)
DPrint(`No Entities mode has been {Enabled and "enabled" or "disabled"}`)
if Enabled then
local Count = 0
for _, Remote in ReplicatedStorage:GetChildren() do
if Remote.Name:sub(1, 4) ~= "Send" then continue end
Settings.RemovedRemotes[Remote] = true
Remote.Parent = nil
Count += 1
end
DPrint(`Removed {Count} entity remote events`)
else
local Count = 0
for Remote in Settings.RemovedRemotes do
Remote.Parent = ReplicatedStorage
Settings.RemovedRemotes[Remote] = nil
Count += 1
end
DPrint(`Restored {Count} entity remote events`)
end
end
})

Groupbox:AddDivider()

Groupbox:AddSlider("StuckDetection", {
Text = "Stuck Detection",
Min = 0.5,
Max = 2.5,
Default = 0.8,
Rounding = 1,
Compact = true,
HideMax = true,
Suffix = "s",
Changed = function(Value)
Settings.StuckDetection = Value
DPrint(`Stuck detection time has been set to {Value}s`)
end
})

Groupbox:AddToggle("DebugLogs", {
Text = "Debug Logs",
Changed = function(Enabled)
Settings.DebugLogs = Enabled
print(`Debug Logs has been {Enabled and "enabled" or "disabled"}`)
end
})

--// End //
do
Library:GiveSignal(RunService.Heartbeat:Connect(function()
if not Settings.Running then return end

local TimeSinceSuccess = os.clock() - Settings.LatestSuccess
if TimeSinceSuccess > Settings.StuckDetection * 3 then
DWarn("Severe stuck detection, restarting autoplay")
task.spawn(function()
Settings.AutoPlay:SetValue(false)
task.wait()
Settings.AutoPlay:SetValue(true)
end)
end

ProcessLatestRooms()
end))

local RoomNumbers = {}
for _, Room in Rooms:GetChildren() do
local RoomNumber = tonumber(Room.Name)
if RoomNumber then
table.insert(RoomNumbers, RoomNumber)
end
end
local MaxNumber = #RoomNumbers > 0 and math.max(unpack(RoomNumbers)) or 0

if MaxNumber < 24 then
Settings.CanStart = false
DWarn("First safe room not passed, autoplay cannot start")
local TimeInstance = Instance.new("Part")
Library:Notify({
Title = "Grace Autoplay",
Description = "Please pass the first safe room, if not, you can't get exp and keys.",
Time = TimeInstance,
SoundId = 4590662766
})
Library:GiveSignal(Rooms.ChildAdded:Connect(function(Child)
if Settings.CanStart then return end
if Child.Name == "24" or Child.Name == "25" then
DPrint("First safe room passed, autoplay can start")
Settings.CanStart = true
TimeInstance:Destroy()
end
end))
else
Settings.CanStart = true
DPrint("First safe room passed, autoplay can start")
end
end
[ View More ]
28edb93a-5465-4f35-8eb2-a1ab1503c0b2.webp


Grace auto farm script works on zen, mayhem and grace. i skidded this from the ms paint addon and it's also intirely open source use the ms paint one for a working patch.
 
Back
Top