local Players = game:GetService("Players") local TweenService = game:GetService("TweenService") local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local player = Players.LocalPlayer -------------------------------------------------------------------- -- THEME PRESETS -------------------------------------------------------------------- local Presets = { ["Pumpkin"] = { Background = Color3.fromRGB(24, 24, 30), TitleBar = Color3.fromRGB(32, 32, 40), Panel = Color3.fromRGB(36, 36, 46), Item = Color3.fromRGB(46, 46, 58), Accent = Color3.fromRGB(255, 140, 0), On = Color3.fromRGB(60, 180, 75), Off = Color3.fromRGB(200, 60, 60), Text = Color3.fromRGB(235, 235, 240), SubText = Color3.fromRGB(150, 150, 165), }, ["Haunted Purple"] = { Background = Color3.fromRGB(28, 18, 40), TitleBar = Color3.fromRGB(38, 24, 54), Panel = Color3.fromRGB(44, 30, 62), Item = Color3.fromRGB(58, 40, 80), Accent = Color3.fromRGB(255, 140, 0), On = Color3.fromRGB(120, 200, 60), Off = Color3.fromRGB(200, 60, 60), Text = Color3.fromRGB(240, 235, 245), SubText = Color3.fromRGB(160, 145, 180), }, ["Midnight"] = { Background = Color3.fromRGB(15, 20, 35), TitleBar = Color3.fromRGB(20, 28, 48), Panel = Color3.fromRGB(26, 36, 60), Item = Color3.fromRGB(36, 48, 78), Accent = Color3.fromRGB(80, 160, 255), On = Color3.fromRGB(60, 180, 120), Off = Color3.fromRGB(210, 70, 80), Text = Color3.fromRGB(230, 236, 250), SubText = Color3.fromRGB(140, 155, 185), }, ["Blood Moon"] = { Background = Color3.fromRGB(25, 10, 12), TitleBar = Color3.fromRGB(40, 14, 18), Panel = Color3.fromRGB(48, 20, 24), Item = Color3.fromRGB(66, 28, 32), Accent = Color3.fromRGB(220, 40, 50), On = Color3.fromRGB(90, 190, 90), Off = Color3.fromRGB(150, 40, 40), Text = Color3.fromRGB(245, 230, 230), SubText = Color3.fromRGB(175, 140, 140), }, ["Toxic Green"] = { Background = Color3.fromRGB(14, 22, 16), TitleBar = Color3.fromRGB(20, 34, 24), Panel = Color3.fromRGB(26, 44, 30), Item = Color3.fromRGB(36, 60, 40), Accent = Color3.fromRGB(120, 230, 60), On = Color3.fromRGB(60, 200, 90), Off = Color3.fromRGB(200, 60, 60), Text = Color3.fromRGB(230, 245, 230), SubText = Color3.fromRGB(140, 175, 145), }, ["Light"] = { Background = Color3.fromRGB(240, 240, 245), TitleBar = Color3.fromRGB(225, 225, 235), Panel = Color3.fromRGB(250, 250, 255), Item = Color3.fromRGB(215, 215, 228), Accent = Color3.fromRGB(255, 140, 0), On = Color3.fromRGB(50, 170, 70), Off = Color3.fromRGB(210, 60, 60), Text = Color3.fromRGB(30, 30, 40), SubText = Color3.fromRGB(110, 110, 125), }, } local PresetNames = { "Pumpkin", "Haunted Purple", "Midnight", "Blood Moon", "Toxic Green", "Light" } local FontSets = { ["Gotham"] = { Regular = Enum.Font.Gotham, Bold = Enum.Font.GothamBold }, ["Fredoka"] = { Regular = Enum.Font.FredokaOne, Bold = Enum.Font.FredokaOne }, ["Source Sans"] = { Regular = Enum.Font.SourceSans, Bold = Enum.Font.SourceSansBold }, ["Arcade"] = { Regular = Enum.Font.Arcade, Bold = Enum.Font.Arcade }, } local FontNames = { "Gotham", "Fredoka", "Source Sans", "Arcade" } -- Live theme state (mutated by the Settings tab) local Theme = {} for k, v in pairs(Presets["Pumpkin"]) do Theme[k] = v end local Fonts = FontSets["Gotham"] local Appearance = { Corner = 1, Transparency = 0 } -------------------------------------------------------------------- -- HELPERS -------------------------------------------------------------------- local connections = {} local allModules = {} local themeBinds = {} local function connect(signal, fn) local c = signal:Connect(fn) table.insert(connections, c) return c end local function make(class, props, parent) local inst = Instance.new(class) for k, v in pairs(props) do inst[k] = v end inst.Parent = parent return inst end -- Runs fn now and again every time the theme changes local function bind(fn) table.insert(themeBinds, fn) fn() end -- Runs at most once per frame, so dragging color sliders doesn't lag local themePending = false local function applyTheme() if themePending then return end themePending = true task.defer(function() themePending = false for _, fn in ipairs(themeBinds) do pcall(fn) end end) end -- skin(inst, { BackgroundColor3 = "Panel", TextColor3 = "Text" }) local function skin(inst, map) bind(function() for prop, key in pairs(map) do inst[prop] = Theme[key] end end) return inst end local function font(inst, bold) bind(function() inst.Font = bold and Fonts.Bold or Fonts.Regular end) end local function corner(inst, radius, fixed) radius = radius or 6 local c = make("UICorner", { CornerRadius = UDim.new(0, radius) }, inst) if not fixed then bind(function() c.CornerRadius = UDim.new(0, math.floor(radius * Appearance.Corner + 0.5)) end) end end local function windowTransparency(inst) bind(function() inst.BackgroundTransparency = Appearance.Transparency end) end local function label(parent, props, bold, colorKey) props.BackgroundTransparency = 1 local l = make("TextLabel", props, parent) skin(l, { TextColor3 = colorKey or "Text" }) font(l, bold) return l end local function isPress(input) return input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch end local function isMove(input) return input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch end local function notify(module, key) if module.OnChange then local ok, err = pcall(module.OnChange, module, key) if not ok then warn("[" .. module.Name .. "] OnChange error:", err) end end end -------------------------------------------------------------------- -- MAIN WINDOW -------------------------------------------------------------------- local screenGui = make("ScreenGui", { Name = "ModuleHub", ResetOnSpawn = false, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, }, player:WaitForChild("PlayerGui")) local main = make("Frame", { Size = UDim2.fromOffset(500, 360), AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.new(0.5, 0, 0.5, 0), BorderSizePixel = 0, }, screenGui) skin(main, { BackgroundColor3 = "Background" }) windowTransparency(main) corner(main, 10) local uiScale = make("UIScale", { Scale = 1 }, main) local titleBar = make("Frame", { Size = UDim2.new(1, 0, 0, 36), BorderSizePixel = 0, }, main) skin(titleBar, { BackgroundColor3 = "TitleBar" }) windowTransparency(titleBar) corner(titleBar, 10) -- square off the bottom corners of the title bar local titleFix = make("Frame", { Size = UDim2.new(1, 0, 0, 10), Position = UDim2.new(0, 0, 1, -10), BorderSizePixel = 0, }, titleBar) skin(titleFix, { BackgroundColor3 = "TitleBar" }) windowTransparency(titleFix) local titleLabel = label(titleBar, { Size = UDim2.new(1, -60, 1, 0), Position = UDim2.new(0, 14, 0, 0), Text = "🎃 Module Hub", TextSize = 16, TextXAlignment = Enum.TextXAlignment.Left, }, true, "Accent") local closeButton = make("TextButton", { Size = UDim2.fromOffset(28, 28), Position = UDim2.new(1, -34, 0, 4), Text = "X", TextColor3 = Color3.new(1, 1, 1), TextSize = 14, AutoButtonColor = true, }, titleBar) skin(closeButton, { BackgroundColor3 = "Off" }) font(closeButton, true) corner(closeButton, 6) -- Dragging do local dragging, dragStart, startPos = false, nil, nil connect(titleBar.InputBegan, function(input) if isPress(input) then dragging = true dragStart = input.Position startPos = main.Position end end) connect(UserInputService.InputChanged, function(input) if dragging and isMove(input) 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) connect(UserInputService.InputEnded, function(input) if isPress(input) then dragging = false end end) end -- Tab bar (left) and content area (right) local tabBar = make("Frame", { Size = UDim2.new(0, 120, 1, -36), Position = UDim2.new(0, 0, 0, 36), BorderSizePixel = 0, }, main) skin(tabBar, { BackgroundColor3 = "Panel" }) windowTransparency(tabBar) make("UIListLayout", { Padding = UDim.new(0, 4), SortOrder = Enum.SortOrder.LayoutOrder, }, tabBar) make("UIPadding", { PaddingTop = UDim.new(0, 8), PaddingLeft = UDim.new(0, 8), PaddingRight = UDim.new(0, 8), }, tabBar) local content = make("Frame", { Size = UDim2.new(1, -120, 1, -36), Position = UDim2.new(0, 120, 0, 36), BackgroundTransparency = 1, }, main) -------------------------------------------------------------------- -- WIDGETS -------------------------------------------------------------------- local function createSlider(parent, setting, module) local min, max = setting.Min, setting.Max local step = setting.Step or 1 local suffix = setting.Suffix or "" local frame = make("Frame", { Size = UDim2.new(1, 0, 0, 42), BackgroundTransparency = 1, }, parent) label(frame, { Size = UDim2.new(0.6, 0, 0, 18), Text = setting.Name, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left, }, false) local valueLabel = label(frame, { Size = UDim2.new(0.4, 0, 0, 18), Position = UDim2.new(0.6, 0, 0, 0), TextSize = 13, TextXAlignment = Enum.TextXAlignment.Right, }, true, "Accent") local track = make("Frame", { Size = UDim2.new(1, 0, 0, 8), Position = UDim2.new(0, 0, 0, 26), BorderSizePixel = 0, }, frame) skin(track, { BackgroundColor3 = "Item" }) corner(track, 4, true) local fill = make("Frame", { Size = UDim2.new(0, 0, 1, 0), BorderSizePixel = 0, }, track) skin(fill, { BackgroundColor3 = "Accent" }) corner(fill, 4, true) local knob = make("Frame", { Size = UDim2.fromOffset(14, 14), AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.new(0, 0, 0.5, 0), BackgroundColor3 = Color3.new(1, 1, 1), BorderSizePixel = 0, }, track) corner(knob, 7, true) local function setValue(v, silent) v = math.clamp(v, min, max) v = min + math.floor((v - min) / step + 0.5) * step v = math.clamp(tonumber(string.format("%.4f", v)), min, max) module.Values[setting.Key] = v local alpha = (v - min) / (max - min) fill.Size = UDim2.new(alpha, 0, 1, 0) knob.Position = UDim2.new(alpha, 0, 0.5, 0) if step < 1 then valueLabel.Text = string.format("%.2f", v) .. suffix else valueLabel.Text = string.format("%d", math.floor(v + 0.5)) .. suffix end if not silent then notify(module, setting.Key) end end local function updateFromInput(input) local width = track.AbsoluteSize.X if width <= 0 then return end local alpha = math.clamp((input.Position.X - track.AbsolutePosition.X) / width, 0, 1) setValue(min + (max - min) * alpha) end -- only listens for mouse movement while you're actually dragging local moveConn, endConn local function stopDrag() if moveConn then moveConn:Disconnect() moveConn = nil end if endConn then endConn:Disconnect() endConn = nil end end connect(track.InputBegan, function(input) if isPress(input) then updateFromInput(input) stopDrag() moveConn = UserInputService.InputChanged:Connect(function(i) if isMove(i) then updateFromInput(i) end end) endConn = UserInputService.InputEnded:Connect(function(i) if isPress(i) then stopDrag() end end) end end) -- make sure a drag listener can never outlive the GUI connect(frame.Destroying, stopDrag) module.Setters[setting.Key] = setValue setValue(module.Values[setting.Key], true) end local function createToggle(parent, setting, module) local frame = make("Frame", { Size = UDim2.new(1, 0, 0, 28), BackgroundTransparency = 1, }, parent) label(frame, { Size = UDim2.new(1, -60, 1, 0), Text = setting.Name, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left, }, false) local btn = make("TextButton", { Size = UDim2.fromOffset(48, 22), Position = UDim2.new(1, -48, 0.5, -11), TextSize = 12, TextColor3 = Color3.new(1, 1, 1), AutoButtonColor = true, }, frame) font(btn, true) corner(btn, 6) local function refresh() local on = module.Values[setting.Key] btn.Text = on and "ON" or "OFF" btn.BackgroundColor3 = on and Theme.On or Theme.Off end bind(refresh) connect(btn.MouseButton1Click, function() module.Values[setting.Key] = not module.Values[setting.Key] refresh() notify(module, setting.Key) end) module.Setters[setting.Key] = function(v, silent) module.Values[setting.Key] = v refresh() if not silent then notify(module, setting.Key) end end end local function createChoice(parent, setting, module) local frame = make("Frame", { Size = UDim2.new(1, 0, 0, 28), BackgroundTransparency = 1, }, parent) label(frame, { Size = UDim2.new(0.5, 0, 1, 0), Text = setting.Name, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left, }, false) local btn = make("TextButton", { Size = UDim2.new(0.5, 0, 0, 24), Position = UDim2.new(0.5, 0, 0.5, -12), TextSize = 12, AutoButtonColor = true, }, frame) skin(btn, { BackgroundColor3 = "Item", TextColor3 = "Accent" }) font(btn, true) corner(btn, 6) local function refresh() btn.Text = tostring(module.Values[setting.Key]) .. " ▸" end connect(btn.MouseButton1Click, function() local options = setting.Options local index = table.find(options, module.Values[setting.Key]) or 0 index = index % #options + 1 module.Values[setting.Key] = options[index] refresh() notify(module, setting.Key) end) module.Setters[setting.Key] = function(v, silent) module.Values[setting.Key] = v refresh() if not silent then notify(module, setting.Key) end end refresh() end local function createText(parent, setting, module) local frame = make("Frame", { Size = UDim2.new(1, 0, 0, 28), BackgroundTransparency = 1, }, parent) label(frame, { Size = UDim2.new(0.35, 0, 1, 0), Text = setting.Name, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left, }, false) local box = make("TextBox", { Size = UDim2.new(0.65, 0, 0, 24), Position = UDim2.new(0.35, 0, 0.5, -12), Text = module.Values[setting.Key], ClearTextOnFocus = false, TextSize = 12, TextXAlignment = Enum.TextXAlignment.Left, ClipsDescendants = true, }, frame) skin(box, { BackgroundColor3 = "Item", TextColor3 = "Text" }) font(box, false) corner(box, 6) make("UIPadding", { PaddingLeft = UDim.new(0, 8), PaddingRight = UDim.new(0, 8) }, box) connect(box.FocusLost, function() module.Values[setting.Key] = box.Text notify(module, setting.Key) end) module.Setters[setting.Key] = function(v, silent) module.Values[setting.Key] = v box.Text = v if not silent then notify(module, setting.Key) end end end local function createButton(parent, setting, module) local frame = make("Frame", { Size = UDim2.new(1, 0, 0, 28), BackgroundTransparency = 1, }, parent) label(frame, { Size = UDim2.new(0.5, 0, 1, 0), Text = setting.Name, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left, }, false) local btn = make("TextButton", { Size = UDim2.new(0.5, 0, 0, 24), Position = UDim2.new(0.5, 0, 0.5, -12), Text = setting.Text or "Run", TextSize = 12, AutoButtonColor = true, }, frame) skin(btn, { BackgroundColor3 = "Accent" }) btn.TextColor3 = Color3.new(0, 0, 0) font(btn, true) corner(btn, 6) connect(btn.MouseButton1Click, function() if setting.Action then local ok, err = pcall(setting.Action, module) if not ok then warn("[" .. module.Name .. "] button error:", err) end end end) end local function createDropdown(parent, setting, module) local frame = make("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, }, parent) make("UIListLayout", { Padding = UDim.new(0, 4), SortOrder = Enum.SortOrder.LayoutOrder, }, frame) local row = make("Frame", { Size = UDim2.new(1, 0, 0, 28), BackgroundTransparency = 1, LayoutOrder = 1, }, frame) label(row, { Size = UDim2.new(0.3, 0, 1, 0), Text = setting.Name, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left, }, false) local btn = make("TextButton", { Size = UDim2.new(0.7, 0, 0, 24), Position = UDim2.new(0.3, 0, 0.5, -12), TextSize = 12, AutoButtonColor = true, }, row) skin(btn, { BackgroundColor3 = "Item", TextColor3 = "Accent" }) font(btn, true) corner(btn, 6) local list = make("ScrollingFrame", { Size = UDim2.new(1, 0, 0, 130), BorderSizePixel = 0, ScrollBarThickness = 4, CanvasSize = UDim2.new(), AutomaticCanvasSize = Enum.AutomaticSize.Y, Visible = false, LayoutOrder = 2, }, frame) skin(list, { BackgroundColor3 = "Item", ScrollBarImageColor3 = "Accent" }) corner(list, 6) make("UIListLayout", { Padding = UDim.new(0, 2), SortOrder = Enum.SortOrder.LayoutOrder, }, list) make("UIPadding", { PaddingTop = UDim.new(0, 4), PaddingLeft = UDim.new(0, 4), PaddingRight = UDim.new(0, 4), PaddingBottom = UDim.new(0, 4), }, list) local optionButtons = {} local function refresh() btn.Text = tostring(module.Values[setting.Key]) .. (list.Visible and " ▾" or " ▸") for name, b in pairs(optionButtons) do local selected = (name == module.Values[setting.Key]) b.BackgroundColor3 = selected and Theme.Accent or Theme.Panel b.TextColor3 = selected and Color3.new(0, 0, 0) or Theme.Text end end for i, name in ipairs(setting.Options) do local ob = make("TextButton", { Size = UDim2.new(1, -6, 0, 24), Text = name, TextSize = 12, LayoutOrder = i, AutoButtonColor = false, BorderSizePixel = 0, }, list) font(ob, false) corner(ob, 4) optionButtons[name] = ob connect(ob.MouseButton1Click, function() module.Values[setting.Key] = name list.Visible = false refresh() notify(module, setting.Key) end) end connect(btn.MouseButton1Click, function() list.Visible = not list.Visible refresh() end) module.Setters[setting.Key] = function(v, silent) module.Values[setting.Key] = v refresh() if not silent then notify(module, setting.Key) end end bind(refresh) end -------------------------------------------------------------------- -- ERROR POPUPS (fade out slowly) -------------------------------------------------------------------- local toastHolder = make("Frame", { Size = UDim2.new(0, 380, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, AnchorPoint = Vector2.new(0.5, 0), Position = UDim2.new(0.5, 0, 0, 16), BackgroundTransparency = 1, }, screenGui) make("UIListLayout", { Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder, HorizontalAlignment = Enum.HorizontalAlignment.Center, }, toastHolder) local lastToast, lastToastTime = "", 0 -- notifyError("simple explanation", "technical details (optional)") local function notifyError(message, detail) -- don't spam the same message over and over if message == lastToast and os.clock() - lastToastTime < 4 then return end lastToast, lastToastTime = message, os.clock() -- keep at most 4 popups on screen local existing = {} for _, child in ipairs(toastHolder:GetChildren()) do if child:IsA("Frame") then table.insert(existing, child) end end if #existing >= 4 then existing[1]:Destroy() end local box = make("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundColor3 = Color3.fromRGB(40, 16, 16), BackgroundTransparency = 0.1, BorderSizePixel = 0, }, toastHolder) corner(box, 8, true) make("UIPadding", { PaddingTop = UDim.new(0, 8), PaddingBottom = UDim.new(0, 8), PaddingLeft = UDim.new(0, 12), PaddingRight = UDim.new(0, 12), }, box) make("UIListLayout", { Padding = UDim.new(0, 3), SortOrder = Enum.SortOrder.LayoutOrder, }, box) local stroke = make("UIStroke", { Color = Color3.fromRGB(255, 90, 80), Thickness = 1.5, }, box) local labels = {} table.insert(labels, make("TextLabel", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, Text = "⚠ " .. tostring(message), TextWrapped = true, TextColor3 = Color3.fromRGB(255, 130, 120), Font = Enum.Font.GothamBold, TextSize = 14, TextXAlignment = Enum.TextXAlignment.Left, LayoutOrder = 1, }, box)) if detail then table.insert(labels, make("TextLabel", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, Text = "Details: " .. tostring(detail), TextWrapped = true, TextColor3 = Color3.fromRGB(200, 170, 170), Font = Enum.Font.Gotham, TextSize = 11, TextXAlignment = Enum.TextXAlignment.Left, LayoutOrder = 2, }, box)) end -- hold for a moment, then fade away slowly task.spawn(function() task.wait(3) if not box.Parent then return end local info = TweenInfo.new(2.5, Enum.EasingStyle.Quad, Enum.EasingDirection.In) TweenService:Create(box, info, { BackgroundTransparency = 1 }):Play() TweenService:Create(stroke, info, { Transparency = 1 }):Play() for _, l in ipairs(labels) do TweenService:Create(l, info, { TextTransparency = 1 }):Play() end task.wait(2.6) if box.Parent then box:Destroy() end end) end -------------------------------------------------------------------- -- TABS + MODULES -------------------------------------------------------------------- local tabs = {} local selectedTab = nil local function selectTab(tab) selectedTab = tab for _, t in ipairs(tabs) do local active = (t == tab) t.Page.Visible = active t.Button.BackgroundColor3 = active and Theme.Accent or Theme.Item t.Button.TextColor3 = active and Color3.new(0, 0, 0) or Theme.Text end end -- keep the tab buttons in sync with theme changes bind(function() if selectedTab then selectTab(selectedTab) end end) local function addTab(name) local tab = { Name = name } tab.Button = make("TextButton", { Size = UDim2.new(1, 0, 0, 30), Text = name, TextSize = 13, LayoutOrder = #tabs + 1, AutoButtonColor = false, }, tabBar) font(tab.Button, true) corner(tab.Button, 6) tab.Page = make("ScrollingFrame", { Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 4, CanvasSize = UDim2.new(), AutomaticCanvasSize = Enum.AutomaticSize.Y, Visible = false, }, content) skin(tab.Page, { ScrollBarImageColor3 = "Accent" }) make("UIListLayout", { Padding = UDim.new(0, 8), SortOrder = Enum.SortOrder.LayoutOrder, }, tab.Page) make("UIPadding", { PaddingTop = UDim.new(0, 8), PaddingLeft = UDim.new(0, 8), PaddingRight = UDim.new(0, 12), PaddingBottom = UDim.new(0, 8), }, tab.Page) connect(tab.Button.MouseButton1Click, function() selectTab(tab) end) table.insert(tabs, tab) if not selectedTab then selectTab(tab) else selectTab(selectedTab) end return tab end --[[ addModule(tab, { Name = "My Module", Description = "What it does", NoToggle = false, -- true = no ON/OFF button (used for settings-only modules) Open = false, -- true = settings panel starts expanded Settings = { { Key = "Speed", Name = "Speed", Type = "Slider", Min = 1, Max = 100, Default = 50, Step = 1, Suffix = " studs/s" }, { Key = "Flag", Name = "Option", Type = "Toggle", Default = true }, { Key = "Mode", Name = "Mode", Type = "Choice", Options = { "A", "B" }, Default = "A" }, { Key = "Pick", Name = "Pick", Type = "Dropdown", Options = { "A", "B", "C" }, Default = "A" }, { Key = "Label", Name = "Label", Type = "Text", Default = "hello" }, { Name = "Do thing", Type = "Button", Text = "Run", Action = function(module) end }, }, OnEnable = function(module) end, OnDisable = function(module) end, OnChange = function(module, key) end, -- fires when any setting changes }) ]] local function addModule(tab, cfg) local module = { Name = cfg.Name, Enabled = false, Values = {}, Setters = {}, Config = cfg, OnChange = cfg.OnChange, } for _, s in ipairs(cfg.Settings or {}) do if s.Key then module.Values[s.Key] = s.Default end end table.insert(allModules, module) local container = make("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BorderSizePixel = 0, LayoutOrder = #allModules, }, tab.Page) skin(container, { BackgroundColor3 = "Panel" }) corner(container, 8) make("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, }, container) -- Header row local header = make("Frame", { Size = UDim2.new(1, 0, 0, 48), BackgroundTransparency = 1, LayoutOrder = 1, }, container) label(header, { Size = UDim2.new(1, -130, 0, 22), Position = UDim2.new(0, 12, 0, 6), Text = cfg.Name, TextSize = 14, TextXAlignment = Enum.TextXAlignment.Left, }, true) label(header, { Size = UDim2.new(1, -130, 0, 16), Position = UDim2.new(0, 12, 0, 26), Text = cfg.Description or "", TextSize = 11, TextXAlignment = Enum.TextXAlignment.Left, TextTruncate = Enum.TextTruncate.AtEnd, }, false, "SubText") local toggleButton = make("TextButton", { Size = UDim2.fromOffset(56, 28), Position = UDim2.new(1, -104, 0.5, -14), TextSize = 13, TextColor3 = Color3.new(1, 1, 1), AutoButtonColor = true, Visible = not cfg.NoToggle, }, header) font(toggleButton, true) corner(toggleButton, 6) local function refreshToggle() toggleButton.Text = module.Enabled and "ON" or "OFF" toggleButton.BackgroundColor3 = module.Enabled and Theme.On or Theme.Off end bind(refreshToggle) function module.SetEnabled(state) if cfg.NoToggle or module.Enabled == state then return end module.Enabled = state refreshToggle() local callback = state and cfg.OnEnable or cfg.OnDisable if callback then local ok, err = pcall(callback, module) if not ok then warn("[" .. cfg.Name .. "] error:", err) end end end connect(toggleButton.MouseButton1Click, function() module.SetEnabled(not module.Enabled) end) -- Settings panel + gear button if cfg.Settings and #cfg.Settings > 0 then local gear = make("TextButton", { Size = UDim2.fromOffset(32, 28), Position = UDim2.new(1, -40, 0.5, -14), Text = "⚙", TextSize = 18, AutoButtonColor = true, }, header) font(gear, true) corner(gear, 6) local settingsFrame = make("Frame", { Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, Visible = cfg.Open == true, LayoutOrder = 2, }, container) make("UIListLayout", { Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder, }, settingsFrame) make("UIPadding", { PaddingLeft = UDim.new(0, 12), PaddingRight = UDim.new(0, 12), PaddingBottom = UDim.new(0, 10), PaddingTop = UDim.new(0, 2), }, settingsFrame) for _, s in ipairs(cfg.Settings) do if s.Type == "Slider" then createSlider(settingsFrame, s, module) elseif s.Type == "Toggle" then createToggle(settingsFrame, s, module) elseif s.Type == "Choice" then createChoice(settingsFrame, s, module) elseif s.Type == "Dropdown" then createDropdown(settingsFrame, s, module) elseif s.Type == "Text" then createText(settingsFrame, s, module) elseif s.Type == "Button" then createButton(settingsFrame, s, module) end end local function refreshGear() local open = settingsFrame.Visible gear.BackgroundColor3 = open and Theme.Accent or Theme.Item gear.TextColor3 = open and Color3.new(0, 0, 0) or Theme.Text end bind(refreshGear) connect(gear.MouseButton1Click, function() settingsFrame.Visible = not settingsFrame.Visible refreshGear() end) end return module end -- Resets every setting in a module back to its default local function resetModule(module) for _, s in ipairs(module.Config.Settings) do if s.Key and module.Setters[s.Key] then module.Setters[s.Key](s.Default, true) end end notify(module, nil) end -------------------------------------------------------------------- -- CLOSE BUTTON: stop everything, then destroy the GUI -------------------------------------------------------------------- connect(closeButton.MouseButton1Click, function() for _, module in ipairs(allModules) do module.SetEnabled(false) end for _, c in ipairs(connections) do c:Disconnect() end screenGui:Destroy() end) -- Keybind that hides/shows the window without stopping anything local appearanceModule, windowModule connect(UserInputService.InputBegan, function(input, processed) if processed then return end local key = windowModule and windowModule.Values.Keybind or "RightShift" if input.KeyCode.Name == key then main.Visible = not main.Visible end end) -------------------------------------------------------------------- -- TAB: AUTO FARM -------------------------------------------------------------------- local autoTab = addTab("Auto Farm") -------------------------------------------------------------------- -- Auto Ascend -------------------------------------------------------------------- do local GuiService = game:GetService("GuiService") local session = 0 local lastPress = 0 local Suffixes = { K = 1e3, THOUSAND = 1e3, M = 1e6, MILLION = 1e6, B = 1e9, BILLION = 1e9, T = 1e12, TRILLION = 1e12, QA = 1e15, QUADRILLION = 1e15, QI = 1e18, QUINTILLION = 1e18, SX = 1e21, SEXTILLION = 1e21, SP = 1e24, SEPTILLION = 1e24, OC = 1e27, OCTILLION = 1e27, NO = 1e30, NONILLION = 1e30, DC = 1e33, DECILLION = 1e33, } local function parseAmount(text) text = tostring(text) text = (text:gsub("<[^>]+>", "")) text = (text:gsub(",", "")) local num, suffix = text:match("(%d[%d%.]*)%s*(%a*)") num = tonumber(num) if not num then return nil end local mult = Suffixes[string.upper(suffix or "")] or 1 return num * mult end local function listStats() local stats = player:FindFirstChild("leaderstats") local names = {} if stats then for _, c in ipairs(stats:GetChildren()) do table.insert(names, c.Name) end end return table.concat(names, ", ") end local function getStat(statName) local stats = player:FindFirstChild("leaderstats") if not stats then return nil, "leaderstats folder not found" end local stat for _, child in ipairs(stats:GetChildren()) do if string.lower(child.Name) == string.lower(statName) then stat = child break end end if not stat then return nil, "No leaderstat named '" .. statName .. "'. Available: " .. listStats() end local v = stat.Value if type(v) == "number" then return v end local parsed = parseAmount(v) if not parsed then return nil, "Couldn't read a number from '" .. tostring(v) .. "'" end return parsed end local function getParts() local pg = player:FindFirstChildOfClass("PlayerGui") if not pg then return nil, "PlayerGui not found" end local gameGui = pg:FindFirstChild("gameGui") or pg:FindFirstChild("gameGui", true) if not gameGui then return nil, "gameGui not found" end local menu = gameGui:FindFirstChild("ascendMenu", true) if not menu then return nil, "ascendMenu not found inside gameGui" end local neededLabel = menu:FindFirstChild("neededLabel", true) local amount = (neededLabel and neededLabel:FindFirstChild("amountLabel", true)) or menu:FindFirstChild("amountLabel", true) if not amount then return nil, "amountLabel not found inside ascendMenu" end local confirm = menu:FindFirstChild("confirmButton", true) if not confirm then return nil, "confirmButton not found inside ascendMenu" end local autoBtn = gameGui:FindFirstChild("autoRebirthButton", true) return { amount = amount, confirm = confirm, autoBtn = autoBtn } end -- all text found on a button and its children local function dumpTexts(btn) local texts = {} if btn:IsA("TextButton") or btn:IsA("TextLabel") then table.insert(texts, btn.Text) end for _, d in ipairs(btn:GetDescendants()) do if d:IsA("TextLabel") or d:IsA("TextButton") then table.insert(texts, d.Text) end end return table.concat(texts, " / ") end -- true (ON) / false (OFF) / nil (can't tell) from the button's text local function readAutoState(btn) local joined = string.lower(dumpTexts(btn)) if joined:find("%f[%a]on%f[%A]") then return true end if joined:find("%f[%a]off%f[%A]") then return false end return nil end -- fingerprint of how the button looks, so we can tell if a click changed it local function snapshot(btn) local parts = {} local function add(i) local s = i.Name .. ":" if i:IsA("GuiObject") then s = s .. tostring(i.Visible) .. tostring(i.BackgroundColor3) .. tostring(i.BackgroundTransparency) end if i:IsA("TextLabel") or i:IsA("TextButton") then s = s .. i.Text .. tostring(i.TextColor3) end if i:IsA("ImageLabel") or i:IsA("ImageButton") then s = s .. tostring(i.ImageColor3) .. i.Image end table.insert(parts, s) end add(btn) for _, d in ipairs(btn:GetDescendants()) do add(d) end return table.concat(parts, "|") end ---------------------------------------------------------------- -- Button pressing: tries several methods, one at a time ---------------------------------------------------------------- local function getGlobal(name) local ok, v = pcall(function() return getfenv()[name] end) if ok and type(v) == "function" then return v end local ok2, v2 = pcall(function() return (name == "firesignal" and firesignal) or (name == "getconnections" and getconnections) or nil end) if ok2 and type(v2) == "function" then return v2 end return nil end -- the button itself plus any clickable buttons inside it local function clickTargets(btn) local list = { btn } for _, d in ipairs(btn:GetDescendants()) do if d:IsA("GuiButton") then table.insert(list, d) end end return list end local function methodsFor(btn) local list = {} local fire = getGlobal("firesignal") local conns = getGlobal("getconnections") for _, target in ipairs(clickTargets(btn)) do if target:IsA("GuiButton") then if fire then for _, n in ipairs({ "MouseButton1Click", "Activated", "MouseButton1Down" }) do table.insert(list, { name = "firesignal " .. n .. " on " .. target.Name, run = function() fire(target[n]) return true end, }) end end if conns then for _, n in ipairs({ "MouseButton1Click", "Activated" }) do table.insert(list, { name = "connections " .. n .. " on " .. target.Name, run = function() local any = false for _, c in ipairs(conns(target[n])) do if pcall(function() c:Fire() end) or pcall(function() c.Function() end) then any = true end end return any end, }) end end end end -- real mouse click, with the Module Hub hidden so it can't block the button table.insert(list, { name = "mouse click", run = function() if btn.AbsoluteSize.X <= 0 or btn.AbsoluteSize.Y <= 0 then return false end local vim = game:GetService("VirtualInputManager") local sg = btn:FindFirstAncestorOfClass("ScreenGui") local inset = Vector2.zero if sg and not sg.IgnoreGuiInset then inset = GuiService:GetGuiInset() end local pos = btn.AbsolutePosition + btn.AbsoluteSize / 2 + inset local wasVisible = main.Visible main.Visible = false task.wait(0.05) local ok, err = pcall(function() vim:SendMouseMoveEvent(pos.X, pos.Y, game) task.wait(0.05) vim:SendMouseButtonEvent(pos.X, pos.Y, 0, true, game, 0) task.wait(0.08) vim:SendMouseButtonEvent(pos.X, pos.Y, 0, false, game, 0) end) main.Visible = wasVisible if not ok then error(err) end return true end, }) return list end -- waits up to `seconds` for verify() to become true local function waitFor(verify, seconds) local t = 0 while t < seconds do if verify() then return true end task.wait(0.1) t += 0.1 end return verify() end -- verify (optional): returns true once the click had an effect. -- returns: true, methodName OR false, reason local function pressButton(btn, verify) local ranAny = false for _, m in ipairs(methodsFor(btn)) do local ok, res = pcall(m.run) if ok and res then ranAny = true if not verify then return true, m.name end -- give the game time to react before trying anything else if waitFor(verify, 1) then return true, m.name end end end if ranAny then return false, "clicked, but nothing on the button changed" end return false, "your script runner has no way to click buttons (no firesignal, getconnections or virtual mouse)" end ---------------------------------------------------------------- -- Remote recorder: learns what the game sends when you click Auto Rebirth ---------------------------------------------------------------- local recordedCall = nil local recording = false local hookInstalled = false local callLog = {} local function envFunc(name) local f = getGlobal(name) if f then return f end local ok, v = pcall(function() return getgenv()[name] end) if ok and type(v) == "function" then return v end return nil end local function installHook() if hookInstalled then return true end local hm = envFunc("hookmetamethod") local gnm = envFunc("getnamecallmethod") if not (hm and gnm) then return false end local wrap = envFunc("newcclosure") or function(f) return f end local old old = hm(game, "__namecall", wrap(function(self, ...) if recording then local method = gnm() if method == "FireServer" or method == "InvokeServer" then local okc, isRemote = pcall(function() return typeof(self) == "Instance" and (self:IsA("RemoteEvent") or self:IsA("RemoteFunction")) end) if okc and isRemote then table.insert(callLog, { remote = self, method = method, args = table.pack(...) }) end end end return old(self, ...) end)) hookInstalled = true return true end local function describeArgs(args) local out = {} for i = 1, args.n do table.insert(out, tostring(args[i])) end return table.concat(out, ", ") end local function fireRecorded() local c = recordedCall if not c or not c.remote.Parent then return false end if c.method == "FireServer" then c.remote:FireServer(table.unpack(c.args, 1, c.args.n)) else task.spawn(function() c.remote:InvokeServer(table.unpack(c.args, 1, c.args.n)) end) end return true end local function recordRemote() if not installHook() then notifyError( "Your script runner can't watch remotes (no hookmetamethod).", "Use a remote spy to find the Auto Rebirth remote and send me its name" ) return end callLog = {} recording = true notifyError("Recording for 6 seconds. Click Auto Rebirth by hand now to turn it OFF.") task.delay(6, function() recording = false -- ignore remotes that fire constantly (they're not the button) local counts = {} for _, c in ipairs(callLog) do counts[c.remote] = (counts[c.remote] or 0) + 1 end local pick for _, c in ipairs(callLog) do if counts[c.remote] <= 2 then pick = c break end end if pick then recordedCall = pick notifyError( "Recorded: " .. pick.remote.Name .. ". Auto Ascend will use it to turn Auto Rebirth off.", pick.remote:GetFullName() .. " | args: " .. describeArgs(pick.args) ) else notifyError( "Didn't catch anything. Press Record again and click Auto Rebirth within 6 seconds.", #callLog .. " remote calls seen, all too frequent to be the button" ) end end) end local function testRecorded() if not recordedCall then notifyError("Nothing recorded yet. Press 'Record' first.") return end fireRecorded() notifyError("Fired " .. recordedCall.remote.Name .. ". Check if Auto Rebirth changed.") end ---------------------------------------------------------------- -- Diagnostics ---------------------------------------------------------------- local function checkNow(module) local parts, missing = getParts() if not parts then notifyError("Can't find the Ascend menu parts.", missing) return end local needed = parseAmount(parts.amount.Text) local current, statErr = getStat(module.Values.StatName) local autoText = "button not found" if parts.autoBtn then local s = readAutoState(parts.autoBtn) autoText = (s == true and "ON" or s == false and "OFF" or "can't tell") .. " (text: '" .. dumpTexts(parts.autoBtn) .. "')" end notifyError( "Needed: " .. tostring(needed) .. " | You have: " .. tostring(current or statErr), "amountLabel: '" .. parts.amount.Text .. "' | leaderstats: " .. listStats() .. " | Auto Rebirth: " .. autoText ) end -- clicks Auto Rebirth once so you can see which method works local function testAutoClick(module) local parts, missing = getParts() if not (parts and parts.autoBtn) then notifyError("Can't find the Auto Rebirth button.", missing or "autoRebirthButton not found") return end local before = snapshot(parts.autoBtn) local ok, info = pressButton(parts.autoBtn, function() return snapshot(parts.autoBtn) ~= before end) if ok then notifyError("Click worked using: " .. info .. ". Auto Rebirth just changed, so click it again to put it back.") else notifyError("Auto Rebirth didn't change: " .. info .. ".", "text: '" .. dumpTexts(parts.autoBtn) .. "'") end end ---------------------------------------------------------------- -- Module ---------------------------------------------------------------- addModule(autoTab, { Name = "Auto Ascend", Description = "Presses Ascend when your stat reaches the needed amount", Settings = { { Key = "StatName", Name = "Stat Name", Type = "Text", Default = "Strength" }, { Key = "Interval", Name = "Check Every", Type = "Slider", Min = 0.25, Max = 5, Default = 1, Step = 0.25, Suffix = "s" }, { Key = "Cooldown", Name = "Cooldown After", Type = "Slider", Min = 2, Max = 30, Default = 5, Step = 1, Suffix = "s" }, { Key = "DisableAuto", Name = "Turn Off Auto Rebirth First", Type = "Toggle", Default = true }, { Name = "Show what it reads", Type = "Button", Text = "Check Now", Action = checkNow }, { Name = "Test Auto Rebirth click", Type = "Button", Text = "Test Click", Action = testAutoClick }, { Name = "Learn Auto Rebirth remote", Type = "Button", Text = "Record", Action = recordRemote }, { Name = "Fire recorded remote", Type = "Button", Text = "Test Remote", Action = testRecorded }, }, OnEnable = function(module) session += 1 local mySession = session task.spawn(function() while session == mySession do local ok, err = pcall(function() local values = module.Values if os.clock() - lastPress < values.Cooldown then return end local parts, missing = getParts() if not parts then notifyError("Can't find the Ascend menu parts. The game may have renamed them.", missing) task.wait(2) return end local needed = parseAmount(parts.amount.Text) if not needed then notifyError( "Couldn't read the needed amount from the Ascend menu.", "amountLabel text was '" .. parts.amount.Text .. "'" ) task.wait(2) return end local current, statErr = getStat(values.StatName) if not current then notifyError( "Couldn't read your '" .. values.StatName .. "' stat. Check the Stat Name in the ⚙ settings.", statErr ) task.wait(2) return end if current < needed then return end -- 1) turn auto rebirth off if values.DisableAuto then if recordedCall then fireRecorded() task.wait(0.4) elseif parts.autoBtn then local state = readAutoState(parts.autoBtn) if state == true then local before = snapshot(parts.autoBtn) local pressed, info = pressButton(parts.autoBtn, function() return snapshot(parts.autoBtn) ~= before end) if not pressed then notifyError( "Couldn't turn Auto Rebirth off (" .. tostring(info) .. "). Press 'Record' in the ⚙ so I can learn how. Pressing Ascend anyway.", "text: '" .. dumpTexts(parts.autoBtn) .. "'" ) end task.wait(0.3) end end end -- 2) press Ascend local pressed, info = pressButton(parts.confirm) if pressed then lastPress = os.clock() else notifyError("Couldn't press Ascend: " .. tostring(info) .. ".") end end) if not ok then notifyError("Something unexpected went wrong in Auto Ascend.", err) task.wait(1) end task.wait(math.max(module.Values.Interval, 0.25)) end end) end, OnDisable = function() session += 1 end, }) end -------------------------------------------------------------------- -- Candy Corn Tween -------------------------------------------------------------------- do local session = 0 local currentTween = nil local lastCandy = nil local anchoredRoot = nil local function getRoot() local character = player.Character return character and character:FindFirstChild("HumanoidRootPart") end local function getHumanoid() local character = player.Character return character and character:FindFirstChildOfClass("Humanoid") end local function getPosition(obj) if obj:IsA("BasePart") then return obj.Position elseif obj:IsA("Model") then return obj:GetPivot().Position end return nil end -- Looks inside sub-folders too, and doesn't hang if the folder is missing local function collectCandy() local event = workspace:FindFirstChild("HalloweenEvent") local folder = event and event:FindFirstChild("ActiveCandyCorns") if not folder then return nil end local list = {} local function scan(parent) for _, child in ipairs(parent:GetChildren()) do if child:IsA("BasePart") or child:IsA("Model") then table.insert(list, child) elseif child:IsA("Folder") then scan(child) end end end scan(folder) return list end -- returns: candy OR nil, simpleMessage, detailMessage local function getTarget(values) local root = getRoot() if not root then return nil, "Your character isn't loaded yet.", "HumanoidRootPart not found" end local list = collectCandy() if not list then return nil, "Can't find the candy corn folder. The Halloween event may be over, or the game changed it.", "workspace.HalloweenEvent.ActiveCandyCorns is missing" end if #list == 0 then return nil, "There are no candy corns right now. Waiting for new ones to spawn.", "ActiveCandyCorns is empty" end local candidates = {} local closestTooFar = math.huge for _, candy in ipairs(list) do if not (values.SkipLast and candy == lastCandy) then local pos = getPosition(candy) if pos then local distance = (root.Position - pos).Magnitude if distance <= values.MaxRange then table.insert(candidates, { candy = candy, distance = distance }) else closestTooFar = math.min(closestTooFar, distance) end end end end if #candidates == 0 then if closestTooFar < math.huge then return nil, "The nearest candy corn is too far away (" .. math.floor(closestTooFar) .. " studs). Raise 'Max Range' in the ⚙ settings.", "Max Range is " .. values.MaxRange .. " studs" end return nil, "The only candy corn left is the one you just visited. Waiting for a new one.", "'Skip Last Candy' is on" end if values.Mode == "Random" then return candidates[math.random(1, #candidates)].candy end local best = candidates[1] for _, entry in ipairs(candidates) do if values.Mode == "Closest" and entry.distance < best.distance then best = entry elseif values.Mode == "Farthest" and entry.distance > best.distance then best = entry end end return best.candy end local function releaseAnchor() if anchoredRoot then anchoredRoot.Anchored = false anchoredRoot = nil end end -- returns: true OR false, simpleMessage, detailMessage local function tweenToCandy(candy, values) local root = getRoot() local targetPos = getPosition(candy) if not root then return false, "Your character isn't loaded yet.", "HumanoidRootPart not found" end if not targetPos then return false, "That candy corn disappeared before you could reach it.", "Target has no position" end local finalPos = targetPos + Vector3.new(0, values.HeightOffset, 0) local distance = (root.Position - targetPos).Magnitude local duration = math.max(distance / values.TweenSpeed, 0.05) if values.Anchor then root.Anchored = true anchoredRoot = root end -- cancel gravity/momentum every frame so physics doesn't fight the tween local hb = RunService.Heartbeat:Connect(function() if root.Parent then root.AssemblyLinearVelocity = Vector3.zero root.AssemblyAngularVelocity = Vector3.zero end end) local state local ok, err = pcall(function() local tween = TweenService:Create(root, TweenInfo.new(duration, Enum.EasingStyle.Linear), { CFrame = CFrame.new(finalPos), }) currentTween = tween -- watchdog: if the tween never finishes (respawn, etc.), cancel it task.delay(duration + 3, function() if tween.PlaybackState == Enum.PlaybackState.Playing then tween:Cancel() end end) tween:Play() state = tween.Completed:Wait() end) currentTween = nil hb:Disconnect() releaseAnchor() if not ok then return false, "The tween failed to run.", tostring(err) end -- finished normally, but we're nowhere near the target = the game moved us if state == Enum.PlaybackState.Completed and root.Parent then local off = (root.Position - finalPos).Magnitude if off > 20 then return false, "The game pushed you back, so it may be blocking fast movement. Try lowering 'Tween Speed'.", "Ended " .. math.floor(off) .. " studs away from the target" end end return true end addModule(autoTab, { Name = "Candy Corn Tween", Description = "Tweens you to candy corns one after another", Settings = { { Key = "TweenSpeed", Name = "Tween Speed", Type = "Slider", Min = 10, Max = 300, Default = 80, Step = 1, Suffix = " studs/s" }, { Key = "HeightOffset", Name = "Height Offset", Type = "Slider", Min = 0, Max = 10, Default = 3, Step = 0.5, Suffix = " studs" }, { Key = "Pause", Name = "Pause Between", Type = "Slider", Min = 0, Max = 3, Default = 0.25, Step = 0.05, Suffix = "s" }, { Key = "MaxRange", Name = "Max Range", Type = "Slider", Min = 50, Max = 5000, Default = 2000, Step = 50, Suffix = " studs" }, { Key = "Mode", Name = "Target Mode", Type = "Choice", Options = { "Closest", "Random", "Farthest" }, Default = "Closest" }, { Key = "SkipLast", Name = "Skip Last Candy", Type = "Toggle", Default = true }, { Key = "Anchor", Name = "Anchor While Tweening", Type = "Toggle", Default = false }, }, OnEnable = function(module) session += 1 local mySession = session task.spawn(function() while session == mySession do local ok, err = pcall(function() local hum = getHumanoid() if hum and hum.Health <= 0 then notifyError("You're dead right now. Waiting for you to respawn.") task.wait(1) return end local candy, simple, detail = getTarget(module.Values) if not candy then notifyError(simple, detail) task.wait(1) return end lastCandy = candy local success, s, d = tweenToCandy(candy, module.Values) if not success then notifyError(s, d) task.wait(1) end end) if not ok then notifyError("Something unexpected went wrong in Candy Corn Tween.", err) task.wait(1) end task.wait(math.max(module.Values.Pause, 0.1)) end end) end, OnDisable = function() session += 1 if currentTween then currentTween:Cancel() currentTween = nil end releaseAnchor() lastCandy = nil end, }) end -------------------------------------------------------------------- -- Auto Lift -------------------------------------------------------------------- do local session = 0 local function getHumanoid() local character = player.Character return character and character:FindFirstChildOfClass("Humanoid") end -- looks in the character first (already equipped), then the backpack local function findTool(name) local character = player.Character local tool = character and character:FindFirstChild(name) if tool and tool:IsA("Tool") then return tool end local backpack = player:FindFirstChildOfClass("Backpack") tool = backpack and backpack:FindFirstChild(name) if tool and tool:IsA("Tool") then return tool end return nil end addModule(autoTab, { Name = "Auto Lift", Description = "Equips a workout tool and auto-clicks it", Settings = { { Key = "Exercise", Name = "Exercise", Type = "Dropdown", Options = { "Weight", "Pushups", "Situps", "Handstands" }, Default = "Weight" }, { Key = "CPS", Name = "Click Speed", Type = "Slider", Min = 1, Max = 10, Default = 3, Step = 1, Suffix = " clicks/s" }, { Key = "Unequip", Name = "Unequip When Off", Type = "Toggle", Default = true }, }, OnEnable = function(module) session += 1 local mySession = session task.spawn(function() while session == mySession do local ok, err = pcall(function() local values = module.Values local hum = getHumanoid() if not hum then notifyError("Your character isn't loaded yet.", "Humanoid not found") task.wait(1) return end if hum.Health <= 0 then notifyError("You're dead right now. Waiting for you to respawn.") task.wait(1) return end local tool = findTool(values.Exercise) if not tool then notifyError( "Couldn't find '" .. values.Exercise .. "' in your backpack. You may not have it unlocked yet.", "No Tool named '" .. values.Exercise .. "' in Backpack or Character" ) task.wait(1) return end -- equip it if it isn't already in your hands if tool.Parent ~= player.Character then hum:EquipTool(tool) task.wait(0.15) if tool.Parent ~= player.Character then notifyError( "The game wouldn't let you equip '" .. values.Exercise .. "' right now.", "EquipTool didn't move the tool into your character" ) task.wait(1) return end end tool:Activate() task.wait(math.max(1 / values.CPS, 0.07)) end) if not ok then notifyError("Something unexpected went wrong in Auto Lift.", err) task.wait(1) end end end) end, OnDisable = function(module) session += 1 if module.Values.Unequip then local hum = getHumanoid() if hum then hum:UnequipTools() end end end, }) end -------------------------------------------------------------------- -- TAB: PLAYER -------------------------------------------------------------------- local playerTab = addTab("Player") do local session = 0 addModule(playerTab, { Name = "Walk Speed", Description = "Overrides your walk speed", Settings = { { Key = "Speed", Name = "Walk Speed", Type = "Slider", Min = 16, Max = 200, Default = 50, Step = 1 }, }, OnEnable = function(module) session += 1 local mySession = session task.spawn(function() while session == mySession do local character = player.Character local humanoid = character and character:FindFirstChildOfClass("Humanoid") if humanoid then humanoid.WalkSpeed = module.Values.Speed end task.wait(0.1) end end) end, OnDisable = function() session += 1 local character = player.Character local humanoid = character and character:FindFirstChildOfClass("Humanoid") if humanoid then humanoid.WalkSpeed = 16 end end, }) end -------------------------------------------------------------------- -- TAB: TELEPORTS -------------------------------------------------------------------- local teleportTab = addTab("Teleports") do local GymNames = { "Lobby_Hub", "ZombieGym", "WitchGym", "AntlerGym", "aura gym", "beachToAuraGym", "candy gym", "electric gym", "ice gym", "jungle gym", "eternal gym", "legends gym", "mythical gym", "transcendent gym", "space gym", } local function getRoot() local character = player.Character return character and character:FindFirstChild("HumanoidRootPart") end -- Works for Models, Parts, and Folders (falls back to the first part inside) local function getCFrame(obj) if obj:IsA("Model") then return obj:GetPivot() elseif obj:IsA("BasePart") then return obj.CFrame end local part = obj:FindFirstChildWhichIsA("BasePart", true) return part and part.CFrame or nil end local function teleportTo(name, offset) local root = getRoot() if not root then notifyError("Your character isn't loaded yet.", "HumanoidRootPart not found") return end local target = workspace:FindFirstChild(name, true) if not target then notifyError( "Couldn't find '" .. name .. "'. It may be too far away to load, or named differently.", "'" .. name .. "' not found in workspace" ) return end local cf = getCFrame(target) if not cf then notifyError("'" .. name .. "' has nothing to teleport to.", "No parts inside") return end root.AssemblyLinearVelocity = Vector3.zero root.CFrame = CFrame.new(cf.Position + Vector3.new(0, offset, 0)) end addModule(teleportTab, { Name = "Gym Teleports", Description = "Pick a location, then press Teleport", NoToggle = true, Open = true, Settings = { { Key = "Gym", Name = "Location", Type = "Dropdown", Options = GymNames, Default = "Lobby_Hub" }, { Key = "Height", Name = "Height Offset", Type = "Slider", Min = 0, Max = 50, Default = 5, Step = 1, Suffix = " studs" }, { Name = "Go", Type = "Button", Text = "Teleport to Gym", Action = function(module) teleportTo(module.Values.Gym, module.Values.Height) end, }, }, }) end -------------------------------------------------------------------- -- TAB: SETTINGS (appearance + window) -------------------------------------------------------------------- local settingsTab = addTab("Settings") local function refreshUI() if not (appearanceModule and windowModule) then return end local a, w = appearanceModule.Values, windowModule.Values -- colors local preset = Presets[a.Preset] or Presets["Pumpkin"] for k, v in pairs(preset) do Theme[k] = v end if a.CustomAccent then Theme.Accent = Color3.fromRGB(a.AccentR, a.AccentG, a.AccentB) end -- shape + fonts Appearance.Corner = a.Corner Appearance.Transparency = w.Transparency Fonts = FontSets[a.Font] or FontSets["Gotham"] applyTheme() -- window options uiScale.Scale = w.Scale titleLabel.Text = w.Title if w.SpookyTitle then titleLabel.Font = Enum.Font.Creepster titleLabel.TextSize = 22 else titleLabel.TextSize = 16 end end appearanceModule = addModule(settingsTab, { Name = "Appearance", Description = "Theme, accent color, corners and font", NoToggle = true, Open = true, Settings = { { Key = "Preset", Name = "Theme", Type = "Choice", Options = PresetNames, Default = "Pumpkin" }, { Key = "CustomAccent", Name = "Custom Accent", Type = "Toggle", Default = false }, { Key = "AccentR", Name = "Accent Red", Type = "Slider", Min = 0, Max = 255, Default = 255, Step = 1 }, { Key = "AccentG", Name = "Accent Green", Type = "Slider", Min = 0, Max = 255, Default = 140, Step = 1 }, { Key = "AccentB", Name = "Accent Blue", Type = "Slider", Min = 0, Max = 255, Default = 0, Step = 1 }, { Key = "Corner", Name = "Roundness", Type = "Slider", Min = 0, Max = 2, Default = 1, Step = 0.1, Suffix = "x" }, { Key = "Font", Name = "Font", Type = "Choice", Options = FontNames, Default = "Gotham" }, { Name = "Reset Appearance", Type = "Button", Text = "Reset", Action = resetModule }, }, OnChange = refreshUI, }) windowModule = addModule(settingsTab, { Name = "Window", Description = "Title, size, transparency and hotkey", NoToggle = true, Settings = { { Key = "Title", Name = "Title", Type = "Text", Default = "🎃 Larping Legends Script - Moon/InfStrengthXD" }, { Key = "SpookyTitle", Name = "Spooky Title Font", Type = "Toggle", Default = false }, { Key = "Scale", Name = "UI Size", Type = "Slider", Min = 0.6, Max = 1.4, Default = 1, Step = 0.05, Suffix = "x" }, { Key = "Transparency", Name = "Transparency", Type = "Slider", Min = 0, Max = 0.6, Default = 0, Step = 0.05 }, { Key = "Keybind", Name = "Hide/Show Key", Type = "Choice", Options = { "RightShift", "RightControl", "Insert", "Delete", "K", "M" }, Default = "RightShift" }, { Name = "Reset Window", Type = "Button", Text = "Reset", Action = resetModule }, }, OnChange = refreshUI, }) refreshUI()