--[[ lycan ui v1.0.5 port of the lazyui (imgui) menu, white accent local Lycan = loadstring(game:HttpGet("https://unagitatedly.site/Lycan.lua"))() local Window = Lycan:CreateWindow({ Title = "Lycan" }) local Tab = Window:Tab({ Name = "Visuals", Icon = "visual" }) local Page = Tab:Page({ Name = "ESP" }) local Sec = Page:Section({ Name = "Player options", Side = "Left" }) Sec:Toggle({ Name = "Enable player ESP", Flag = "ESP", Callback = function(v) end }) ]] local Lycan = { Version = "1.0.5", Flags = {}, Options = {}, Folder = "Lycan", AssetBase = "https://unagitatedly.site/lycan/assets/", } -- services local Players = game:GetService("Players") local TweenService = game:GetService("TweenService") local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local HttpService = game:GetService("HttpService") local LocalPlayer = Players.LocalPlayer local function rgb(r, g, b) return Color3.fromRGB(r, g, b) end -- theme (from lazyui theme.hpp, accent 8686ff -> white) local T = { Side = rgb(19, 19, 20), SideTr = 1 - 252 / 255, Content = rgb(19, 19, 20), ContentTr = 1 - 153 / 255, Line = rgb(25, 25, 30), Muted = rgb(84, 86, 101), Hover = rgb(161, 162, 171), Text = rgb(190, 191, 197), White = rgb(255, 255, 255), Accent = rgb(255, 255, 255), OnAccent = rgb(0, 0, 0), Panel = rgb(27, 29, 31), PanelTr = 1 - 128 / 255, PanelHover = rgb(43, 44, 47), PanelPress = rgb(24, 25, 28), SearchFocus = rgb(39, 40, 43), SearchFocusTr = 1 - 130 / 255, Box = rgb(30, 30, 36), BoxHover = rgb(66, 66, 72), -- was 353554, too purple Sep = rgb(29, 29, 37), List = rgb(27, 29, 31), ListTr = 1 - 245 / 255, ListStroke = rgb(255, 255, 255), ListStrokeTr = 1 - 20 / 255, ListActive = rgb(187, 187, 194), } -- motion, same timings as runtime.cpp local DUR = { controls = 0.288, hover = 0.23, press = 0.154, lists = 0.256, nav = 0.329, pages = 0.384 } local SMOOTH = Enum.EasingStyle.Exponential -- fonts local okInter, InterMedium = pcall(Font.new, "rbxasset://fonts/families/Inter.json", Enum.FontWeight.Medium) local okInterB, InterSemi = pcall(Font.new, "rbxasset://fonts/families/Inter.json", Enum.FontWeight.SemiBold) local okTitle, TitleFont = pcall(Font.new, "rbxasset://fonts/families/Montserrat.json", Enum.FontWeight.Bold) if not okInter then InterMedium = Font.fromEnum(Enum.Font.GothamMedium) end if not okInterB then InterSemi = Font.fromEnum(Enum.Font.GothamBold) end if not okTitle then TitleFont = Font.fromEnum(Enum.Font.GothamBold) end local TEXT = 11 -- helpers local function create(class, props, children) local obj = Instance.new(class) local parent for k, v in pairs(props or {}) do if k == "Parent" then parent = v else obj[k] = v end end for _, c in ipairs(children or {}) do c.Parent = obj end if parent then obj.Parent = parent end return obj end local function corner(r) return create("UICorner", { CornerRadius = UDim.new(0, r) }) end local function tween(obj, props, time, style, dir) local t = TweenService:Create(obj, TweenInfo.new(time or DUR.controls, style or SMOOTH, dir or Enum.EasingDirection.Out), props) t:Play() return t end local function safe(fn, ...) if not fn then return end local ok, err = pcall(fn, ...) if not ok then warn("[lycan] " .. tostring(err)) end end local function lerpColor(a, b, t) return a:Lerp(b, math.clamp(t, 0, 1)) end -- connections made while a popup is being built go in here instead of the window list, so they die with the popup local scope -- tweened number, apply() runs every step (hover / state colors) local function animated(initial, apply, cleanup) local nv = Instance.new("NumberValue") nv.Value = initial local conn = nv.Changed:Connect(apply) local list = scope or cleanup if list then list[#list + 1] = conn end apply(initial) local active local self = {} function self.To(target, time) if active then active:Cancel() end active = TweenService:Create(nv, TweenInfo.new(time or DUR.controls, SMOOTH, Enum.EasingDirection.Out), { Value = target }) active:Play() end function self.Set(v) if active then active:Cancel() active = nil end nv.Value = v end function self.Get() return nv.Value end return self end -- label placed by its vertical center local function makeLabel(parent, text, x, cy, color, align) local right = align == "Right" return create("TextLabel", { Parent = parent, BackgroundTransparency = 1, AnchorPoint = Vector2.new(right and 1 or 0, 0), Position = UDim2.fromOffset(x, math.floor(cy - 7 + 0.5)), Size = UDim2.fromOffset(0, 14), AutomaticSize = Enum.AutomaticSize.X, FontFace = InterMedium, TextSize = TEXT, TextColor3 = color, Text = text, TextXAlignment = right and Enum.TextXAlignment.Right or Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Center, }) end -- assets local getAsset = getcustomasset or getsynasset local ASSET_NAMES = { "logo", "logo_pill", "bg_left", "bg_right", "aurora1", "aurora2", "aurora3", "aurora4", "arrow", "arrow_2", "bomb", "check_icon", "cloud", "cross", "expand_up", "expand_up_2", "folder", "folder_add", "misc", "search_bar", "settings", "speed", "star_filled", "user", "visual", "world", } local function ensureFolder(path) if makefolder and isfolder and not isfolder(path) then pcall(makefolder, path) end end -- fetch all pngs at once, cached in the workspace local function loadAssets() local out, pending = {}, #ASSET_NAMES for _, name in ipairs(ASSET_NAMES) do task.spawn(function() pcall(function() if not (getAsset and isfile and writefile) then return end ensureFolder(Lycan.Folder) ensureFolder(Lycan.Folder .. "/assets") local path = Lycan.Folder .. "/assets/" .. Lycan.Version .. "_" .. name .. ".png" -- version in the name so new pngs replace cached ones if not isfile(path) then writefile(path, game:HttpGet(Lycan.AssetBase .. name .. ".png")) end out[name] = getAsset(path) end) out[name] = out[name] or "" pending = pending - 1 end) end local started = os.clock() while pending > 0 and os.clock() - started < 20 do task.wait() end return out end -- device local function detectMobile() if UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled then return true end return false end Lycan.IsMobile = detectMobile() local function inputIsPress(input) return input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch end local guiRef -- the window's screen gui, its origin is where gui coordinates start local function pointerPosition(input) local origin = guiRef and guiRef.AbsolutePosition or Vector2.new(0, 0) if input and input.UserInputType == Enum.UserInputType.Touch then return Vector2.new(input.Position.X, input.Position.Y) - origin end return UserInputService:GetMouseLocation() - origin end local function hostGui() local ok, gui = pcall(function() return (gethui and gethui()) or game:GetService("CoreGui") end) if ok and gui then return gui end return LocalPlayer:WaitForChild("PlayerGui") end -- flags / config local function serialize(v) local t = typeof(v) if t == "Color3" then return { __t = "c", r = v.R, g = v.G, b = v.B } end if t == "EnumItem" then return { __t = "e", n = v.Name } end return v end local function deserialize(v) if type(v) == "table" and v.__t == "c" then return Color3.new(v.r, v.g, v.b) end if type(v) == "table" and v.__t == "e" then return Enum.KeyCode[v.n] end return v end function Lycan:SaveConfig(name) if not (writefile and makefolder) then return false end ensureFolder(self.Folder) ensureFolder(self.Folder .. "/configs") local data = {} for flag, opt in pairs(self.Options) do data[flag] = serialize(opt.Value) end writefile(self.Folder .. "/configs/" .. name .. ".json", HttpService:JSONEncode(data)) return true end function Lycan:LoadConfig(name) if not (readfile and isfile) then return false end local path = self.Folder .. "/configs/" .. name .. ".json" if not isfile(path) then return false end local ok, data = pcall(function() return HttpService:JSONDecode(readfile(path)) end) if not ok then return false end for flag, value in pairs(data) do local opt = self.Options[flag] if opt and opt.Set then opt:Set(deserialize(value)) end end return true end function Lycan:ListConfigs() local out = {} if listfiles and isfolder and isfolder(self.Folder .. "/configs") then for _, f in ipairs(listfiles(self.Folder .. "/configs")) do local n = f:match("([^/\\]+)%.json$") if n then out[#out + 1] = n end end end return out end -- window function Lycan:CreateWindow(opts) opts = opts or {} local Window = { Tabs = {}, Groups = { {} }, Cleanup = {}, Toggled = true, Scale = 1 } local assets = loadAssets() local function asset(name) return assets[name] or "" end local title = opts.Title or "Lycan" local W, H = 800, 478 local SIDE = 210 local gui = create("ScreenGui", { Name = "Lycan", ResetOnSpawn = false, IgnoreGuiInset = true, DisplayOrder = 999, ZIndexBehavior = Enum.ZIndexBehavior.Sibling }) pcall(function() if syn and syn.protect_gui then syn.protect_gui(gui) end end) gui.Parent = hostGui() Window.Gui = gui guiRef = gui local Main = create("Frame", { Name = "Main", Parent = gui, BackgroundTransparency = 1, AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), Size = UDim2.fromOffset(W, H) }) local UIScale = create("UIScale", { Parent = Main, Scale = 1 }) local function autoScale() local vp = workspace.CurrentCamera and workspace.CurrentCamera.ViewportSize or Vector2.new(1920, 1080) return math.min(1, vp.X * 0.96 / W, vp.Y * 0.96 / H) end local userScale = opts.Scale local function applyScale() UIScale.Scale = userScale or autoScale() end applyScale() function Window:SetScale(s) userScale = s applyScale() end function Window:GetScale() return UIScale.Scale end if workspace.CurrentCamera then Window.Cleanup[#Window.Cleanup + 1] = workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(applyScale) end local function connect(signal, fn) local c = signal:Connect(fn) local list = scope or Window.Cleanup list[#list + 1] = c return c end -- background local content = create("Frame", { Name = "Content", Parent = Main, BackgroundTransparency = 1, Position = UDim2.fromOffset(SIDE, 0), Size = UDim2.fromOffset(W - SIDE, H), ClipsDescendants = true }) local auroras = {} for i = 1, 4 do auroras[i] = create("ImageLabel", { Parent = content, BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1), Image = asset("aurora" .. i), ImageColor3 = T.White, ImageTransparency = 1, ScaleType = Enum.ScaleType.Stretch, ZIndex = 2 }) end -- crossfade the aurora frames connect(RunService.RenderStepped, function() if not Window.Toggled or not Window.Glow then return end local phase = (os.clock() / 9) % 4 for i, img in ipairs(auroras) do local d = math.abs(phase - (i - 1)) d = math.min(d, 4 - d) -- cosine blend, neighbours always add up to 1 so the glow never flickers local weight = d < 1 and 0.5 * (1 + math.cos(math.pi * d)) or 0 img.ImageTransparency = 1 - weight * 0.22 end end) local contentBg = create("ImageLabel", { Name = "ContentBg", Parent = content, BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1), Image = asset("bg_right"), ImageColor3 = T.White, ImageTransparency = 1 - (opts.Opacity or (opts.Transparent and 0.6 or 0.92)), ScaleType = Enum.ScaleType.Slice, SliceCenter = Rect.new(1, 28, 36, 36), SliceScale = 0.5, }) local side = create("ImageLabel", { Name = "Sidebar", Parent = Main, BackgroundTransparency = 1, Size = UDim2.fromOffset(SIDE, H), Image = asset("bg_left"), ImageColor3 = T.White, ImageTransparency = T.SideTr, ScaleType = Enum.ScaleType.Slice, SliceCenter = Rect.new(28, 28, 63, 36), SliceScale = 0.5, }) Window.Glow = opts.Glow ~= false function Window:SetGlow(on) self.Glow = on if not on then for _, img in ipairs(auroras) do img.ImageTransparency = 1 end end end Window.Opacity = opts.Opacity or (opts.Transparent and 0.6 or 0.92) function Window:SetOpacity(v) v = math.clamp(v, 0.3, 1) self.Opacity = v contentBg.ImageTransparency = 1 - v side.ImageTransparency = math.max(0, (1 - v) * 0.4) -- the sidebar stays more solid than the content end Window:SetOpacity(Window.Opacity) -- sidebar header local logoImage = opts.Logo if type(logoImage) ~= "string" or logoImage == "" then logoImage = asset("logo") end create("ImageLabel", { Name = "Logo", Parent = side, BackgroundTransparency = 1, Position = UDim2.fromOffset(18, 19), Size = UDim2.fromOffset(18, 18), Image = logoImage, ImageColor3 = T.White }) local titleLabel = create("TextLabel", { Name = "Title", Parent = side, BackgroundTransparency = 1, AnchorPoint = Vector2.new(0, 0), Position = UDim2.fromOffset(54, 18), Size = UDim2.fromOffset(0, 18), AutomaticSize = Enum.AutomaticSize.X, FontFace = TitleFont, TextSize = 15, TextColor3 = T.White, Text = title, TextXAlignment = Enum.TextXAlignment.Left, }) local star = create("ImageLabel", { Name = "Star", Parent = side, BackgroundTransparency = 1, Position = UDim2.fromOffset(132, 16), Size = UDim2.fromOffset(10, 10), Image = asset("star_filled"), ImageColor3 = T.Accent }) local function placeStar() star.Position = UDim2.fromOffset(math.floor(54 + titleLabel.AbsoluteSize.X / UIScale.Scale + 1), 16) end connect(titleLabel:GetPropertyChangedSignal("AbsoluteSize"), placeStar) local searchBg = create("Frame", { Name = "Search", Parent = side, Position = UDim2.fromOffset(0, 55), Size = UDim2.fromOffset(SIDE, 31), BackgroundColor3 = T.Panel, BackgroundTransparency = T.PanelTr, BorderSizePixel = 0 }) create("ImageLabel", { Parent = searchBg, BackgroundTransparency = 1, Size = UDim2.fromOffset(31, 31), Image = asset("search_bar"), ImageColor3 = T.Muted }) local searchBox = create("TextBox", { Parent = searchBg, BackgroundTransparency = 1, Position = UDim2.fromOffset(31, 0), Size = UDim2.fromOffset(164, 31), FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Text, PlaceholderText = "Search", PlaceholderColor3 = T.Muted, Text = "", ClearTextOnFocus = false, TextXAlignment = Enum.TextXAlignment.Left, ClipsDescendants = true, }) local searchFocus = animated(0, function(a) searchBg.BackgroundColor3 = lerpColor(T.Panel, T.SearchFocus, a) searchBg.BackgroundTransparency = T.PanelTr + (T.SearchFocusTr - T.PanelTr) * a end, Window.Cleanup) connect(searchBox.Focused, function() searchFocus.To(1, DUR.controls) end) connect(searchBox.FocusLost, function() searchFocus.To(0, DUR.controls) end) create("Frame", { Name = "HeaderLine", Parent = side, Position = UDim2.fromOffset(0, 100), Size = UDim2.fromOffset(SIDE, 1), BackgroundColor3 = T.Line, BorderSizePixel = 0 }) local nav = create("Frame", { Name = "Nav", Parent = side, BackgroundTransparency = 1, Position = UDim2.fromOffset(0, 101), Size = UDim2.fromOffset(SIDE, H - 101), ClipsDescendants = true }) local highlight = create("Frame", { Name = "Highlight", Parent = nav, Size = UDim2.fromOffset(SIDE, 31), BackgroundColor3 = T.Panel, BackgroundTransparency = T.PanelTr, BorderSizePixel = 0, Visible = false }) create("Frame", { Name = "Pill", Parent = highlight, Position = UDim2.fromOffset(0, 9), Size = UDim2.fromOffset(3, 13), BackgroundColor3 = T.Accent, BorderSizePixel = 0 }, { corner(5) }) -- content header local Overlay = create("Frame", { Name = "Overlay", Parent = Main, BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1), ZIndex = 50 }) local activePopup local function closePopup() if activePopup then local p = activePopup activePopup = nil safe(p.close) end end Window.ClosePopup = closePopup -- fades a whole popup in or out (text, icons, strokes and fills), originals are remembered the first time local fadeSaved = setmetatable({}, { __mode = "k" }) local function fadeTree(root, show, time) local list = root:GetDescendants() table.insert(list, root) for _, d in ipairs(list) do local saved = fadeSaved[d] if not saved then saved = {} if d:IsA("GuiObject") and d.BackgroundTransparency < 1 then saved.BackgroundTransparency = d.BackgroundTransparency end if (d:IsA("TextLabel") or d:IsA("TextButton") or d:IsA("TextBox")) then saved.TextTransparency = d.TextTransparency end if d:IsA("ImageLabel") or d:IsA("ImageButton") then saved.ImageTransparency = d.ImageTransparency end if d:IsA("UIStroke") then saved.Transparency = d.Transparency end fadeSaved[d] = saved end local goal = {} for prop, original in pairs(saved) do goal[prop] = show and original or 1 if show then d[prop] = 1 end end if next(goal) then tween(d, goal, time) end end end local function presentPopup(frame, anchor, mine, onClose) fadeTree(frame, true, DUR.lists) -- a click anywhere else closes the popup. the catcher sits right behind it, so it also swallows that click local catcher = create("TextButton", { Parent = Overlay, Text = "", AutoButtonColor = false, BackgroundTransparency = 1, Position = UDim2.fromOffset(-3000, -3000), Size = UDim2.fromOffset(6800, 6800), ZIndex = 55 }) mine[#mine + 1] = catcher.MouseButton1Down:Connect(function() closePopup() end) activePopup = { frame = frame, anchor = anchor, close = function() fadeTree(frame, false, DUR.lists * 0.6) for _, c in ipairs(mine) do pcall(function() c:Disconnect() end) end catcher:Destroy() task.delay(DUR.lists * 0.7, function() frame:Destroy() end) if onClose then onClose() end end, } end local function overlayPos(absPos) return (absPos - Main.AbsolutePosition) / UIScale.Scale end local function headerButton(x, iconName) local btn = create("TextButton", { Parent = content, AutoButtonColor = false, Text = "", Position = UDim2.fromOffset(x - SIDE, 15), Size = UDim2.fromOffset(35, 35), BackgroundColor3 = T.Panel, BackgroundTransparency = T.PanelTr, BorderSizePixel = 0 }, { corner(6) }) create("ImageLabel", { Parent = btn, BackgroundTransparency = 1, Position = UDim2.fromOffset(12, 12), Size = UDim2.fromOffset(10, 10), Image = asset(iconName), ImageColor3 = T.White }) local hover, press = 0, 0 local function paint() local c = lerpColor(lerpColor(T.Panel, T.PanelHover, hover), T.PanelPress, press) btn.BackgroundColor3 = c end local hv = animated(0, function(v) hover = v paint() end, Window.Cleanup) local pr = animated(0, function(v) press = v paint() end, Window.Cleanup) connect(btn.MouseEnter, function() hv.To(1, DUR.hover) end) connect(btn.MouseLeave, function() hv.To(0, DUR.hover) pr.To(0, DUR.press) end) connect(btn.MouseButton1Down, function() pr.To(1, DUR.press) end) connect(btn.MouseButton1Up, function() pr.To(0, DUR.press) end) return btn end local leftButton = headerButton(225, "folder_add") local settingsButton = headerButton(750, "settings") local combo = create("TextButton", { Name = "PageCombo", Parent = content, AutoButtonColor = false, Text = "", Position = UDim2.fromOffset(275 - SIDE, 15), Size = UDim2.fromOffset(210, 35), BackgroundColor3 = T.Panel, BackgroundTransparency = T.PanelTr, BorderSizePixel = 0, ClipsDescendants = true }, { corner(6) }) local comboText = makeLabel(combo, "", 15, 17.5, T.Muted) local comboArrow = create("ImageLabel", { Parent = combo, BackgroundTransparency = 1, Position = UDim2.fromOffset(182, 11), Size = UDim2.fromOffset(13, 13), Image = asset("arrow"), ImageColor3 = T.White }) local comboHover = animated(0, function(a) combo.BackgroundColor3 = lerpColor(T.Panel, T.PanelHover, a) end, Window.Cleanup) connect(combo.MouseEnter, function() comboHover.To(1, DUR.hover) end) connect(combo.MouseLeave, function() comboHover.To(0, DUR.hover) end) local crumbTab = makeLabel(content, "", 225 - SIDE, 70.1, T.White) local crumbArrow = create("ImageLabel", { Parent = content, BackgroundTransparency = 1, Position = UDim2.fromOffset(270 - SIDE, 65), Size = UDim2.fromOffset(10, 10), Image = asset("arrow_2"), ImageColor3 = T.Muted }) local crumbPage = makeLabel(content, "", 290 - SIDE, 70.1, T.Muted) local function placeCrumb() local w = crumbTab.AbsoluteSize.X / UIScale.Scale crumbArrow.Position = UDim2.fromOffset(math.floor(225 - SIDE + w + 7), 65) crumbPage.Position = UDim2.fromOffset(math.floor(225 - SIDE + w + 27), 63) end connect(crumbTab:GetPropertyChangedSignal("AbsoluteSize"), placeCrumb) -- tabs / pages local selectedTab local navButtons = {} local function layoutNav(animate) local y = 113 local firstGroup = true for _, group in ipairs(Window.Groups) do local shown = {} for _, tab in ipairs(group) do if tab.Match then shown[#shown + 1] = tab else tab.Button.Visible = false end end if #shown > 0 then if not firstGroup then -- sep 12 below the last group, items 12 below the sep local sep = group.Sep if not sep then sep = create("Frame", { Parent = nav, BackgroundColor3 = T.Line, BorderSizePixel = 0, Size = UDim2.fromOffset(SIDE - 20, 1) }) group.Sep = sep end sep.Visible = true sep.Position = UDim2.fromOffset(20, y + 12 - 101) y = y + 12 + 1 + 12 elseif group.Sep then group.Sep.Visible = false end firstGroup = false for i, tab in ipairs(shown) do tab.Button.Visible = true tab.SlotY = y local target = UDim2.fromOffset(0, y - 101) if animate and tab.Placed then tween(tab.Button, { Position = target }, DUR.nav) else tab.Button.Position = target end tab.Placed = true y = y + 31 + (i < #shown and 4 or 0) end elseif group.Sep then group.Sep.Visible = false end end if selectedTab and selectedTab.SlotY then highlight.Visible = true local target = UDim2.fromOffset(0, selectedTab.SlotY - 101) if animate then tween(highlight, { Position = target }, DUR.nav) else highlight.Position = target end end end local currentPage local pageSwitchToken = 0 local function showPage(tab, page, instant) if not page then return end closePopup() pageSwitchToken = pageSwitchToken + 1 local token = pageSwitchToken local old = currentPage currentPage = page crumbTab.Text = tab.Name crumbPage.Text = page.Name comboText.Text = page.Name if old and old ~= page then local o = old o.Group.Visible = false end page.Group.Visible = true page:Update() page.Group.Position = UDim2.fromOffset(15, 90) end local function selectTab(tab, instant) if selectedTab == tab and currentPage == tab.CurrentPage then return end closePopup() local prev = selectedTab selectedTab = tab for _, t in ipairs(Window.Tabs) do local selected = t == tab t.Select.To(selected and 1 or 0, DUR.nav) end layoutNav(not instant) showPage(tab, tab.CurrentPage or tab.Pages[1], instant or prev == nil) end -- page dropdown local function openComboPopup() if not selectedTab then return end local tab = selectedTab local rowH = 35 local count = #tab.Pages local startPos = overlayPos(combo.AbsolutePosition) local frame = create("Frame", { Parent = Overlay, BackgroundColor3 = T.List, BackgroundTransparency = T.ListTr, Position = UDim2.fromOffset(startPos.X, startPos.Y + 41), Size = UDim2.fromOffset(210, rowH * count), BorderSizePixel = 0, ZIndex = 60 }, { corner(6) }) create("UIStroke", { Parent = frame, Color = T.ListStroke, Transparency = T.ListStrokeTr, Thickness = 1 }) local mine = {} scope = mine for i, page in ipairs(tab.Pages) do local row = create("TextButton", { Parent = frame, AutoButtonColor = false, Text = "", BackgroundTransparency = 1, Position = UDim2.fromOffset(0, (i - 1) * rowH), Size = UDim2.fromOffset(210, rowH), ZIndex = 61 }) local rowHover = create("Frame", { Parent = row, Position = UDim2.fromOffset(3, 3), Size = UDim2.new(1, -6, 1, -6), BackgroundColor3 = T.White, BackgroundTransparency = 1, BorderSizePixel = 0, ZIndex = 61 }, { corner(3) }) local txt = makeLabel(row, page.Name, 15, 17, page == tab.CurrentPage and T.ListActive or T.Muted) txt.ZIndex = 62 connect(row.MouseEnter, function() tween(rowHover, { BackgroundTransparency = 1 - 12 / 255 }, DUR.hover) tween(txt, { TextColor3 = T.ListActive }, DUR.hover) end) connect(row.MouseLeave, function() tween(rowHover, { BackgroundTransparency = 1 }, DUR.hover) if page ~= tab.CurrentPage then tween(txt, { TextColor3 = T.Muted }, DUR.hover) end end) connect(row.MouseButton1Click, function() tab.CurrentPage = page closePopup() showPage(tab, page, false) end) end scope = nil tween(comboArrow, { Rotation = 180 }, DUR.lists) presentPopup(frame, combo, mine, function() tween(comboArrow, { Rotation = 0 }, DUR.lists) end) end connect(combo.MouseButton1Click, function() if activePopup and activePopup.anchor == combo then closePopup() else closePopup() openComboPopup() end end) -- dragging, invisible handles over the empty header strips (nothing interactive under them). -- the window eases toward the mouse every frame and sits on float scale positions while moving, then snaps to whole pixels do local dragging, startMouse, startCenter, target, current local function handle(parent, x, y, w, h) local f = create("Frame", { Parent = parent, BackgroundTransparency = 1, Active = true, Position = UDim2.fromOffset(x, y), Size = UDim2.fromOffset(w, h), ZIndex = 8 }) connect(f.InputBegan, function(input) if not inputIsPress(input) then return end dragging, startMouse = true, pointerPosition(input) startCenter = (Main.AbsolutePosition - gui.AbsolutePosition) + Main.AbsoluteSize / 2 current, target = startCenter, startCenter closePopup() end) end handle(side, 0, 0, SIDE, 55) handle(content, 0, 0, W - SIDE, 14) handle(content, 0, 50, W - SIDE, 36) connect(UserInputService.InputChanged, function(input) if not dragging then return end if input.UserInputType ~= Enum.UserInputType.MouseMovement and input.UserInputType ~= Enum.UserInputType.Touch then return end target = startCenter + (pointerPosition(input) - startMouse) end) connect(UserInputService.InputEnded, function(input) if dragging and inputIsPress(input) then dragging = false end end) connect(RunService.RenderStepped, function(dt) if not current then return end local vp = gui.AbsoluteSize current = current + (target - current) * (1 - math.exp(-dt / 0.035)) if not dragging and (target - current).Magnitude < 0.5 then Main.Position = UDim2.fromOffset(math.floor(target.X + 0.5), math.floor(target.Y + 0.5)) current = nil else Main.Position = UDim2.fromScale(current.X / vp.X, current.Y / vp.Y) end end) end -- tab local Tab = {} Tab.__index = Tab function Window:Divider() self.Groups[#self.Groups + 1] = {} return self end function Window:Tab(topts) topts = topts or {} local group = self.Groups[#self.Groups] local tab = setmetatable({ Window = self, Name = topts.Name or "Tab", Icon = topts.Icon, Pages = {}, Match = true, Names = {} }, Tab) local button = create("TextButton", { Parent = nav, AutoButtonColor = false, Text = "", BackgroundTransparency = 1, Size = UDim2.fromOffset(SIDE, 31), Position = UDim2.fromOffset(0, 12), BorderSizePixel = 0 }) local icon = create("ImageLabel", { Parent = button, BackgroundTransparency = 1, Position = UDim2.fromOffset(20, 8), Size = UDim2.fromOffset(15, 15), Image = asset(tab.Icon or "cross"), ImageColor3 = T.Muted }) local text = makeLabel(button, tab.Name, 50, 15.5, T.Muted) tab.Button = button local selected, hover = 0, 0 local function paint() -- hover only counts while not selected local c = lerpColor(lerpColor(T.Muted, T.White, selected), T.Hover, hover * (1 - selected)) icon.ImageColor3 = c text.TextColor3 = c end tab.Select = animated(0, function(v) selected = v paint() end, self.Cleanup) tab.Hover = animated(0, function(v) hover = v paint() end, self.Cleanup) connect(button.MouseEnter, function() if selectedTab ~= tab then tab.Hover.To(1, DUR.hover) end end) connect(button.MouseLeave, function() tab.Hover.To(0, DUR.hover) end) connect(button.MouseButton1Click, function() tab.Hover.To(0, DUR.hover) selectTab(tab) end) group[#group + 1] = tab self.Tabs[#self.Tabs + 1] = tab table.insert(navButtons, button) layoutNav(false) if not selectedTab then -- first tab gets selected once it has a page tab.PendingSelect = true end return tab end -- containers local Container = {} Container.__index = Container local function newContainer(holder, width, compact, onResize) return setmetatable({ Holder = holder, Width = width, Compact = compact, Items = {}, Height = 0, OnResize = onResize }, Container) end function Container:Update() local y = 0 local gap = self.Compact and 10 or 12 local count = 0 for _, item in ipairs(self.Items) do if item.Visible ~= false then count = count + 1 end end local index = 0 for _, item in ipairs(self.Items) do if item.Visible ~= false then index = index + 1 item.Frame.Visible = true item.Frame.Position = UDim2.fromOffset(0, y) y = y + item.Height if item.Sep then item.Sep.Visible = false end if index < count then if not self.Compact then if not item.Sep then item.Sep = create("Frame", { Parent = self.Holder, BackgroundColor3 = T.Sep, BorderSizePixel = 0 }) end item.Sep.Visible = true item.Sep.Position = UDim2.fromOffset(25, y + gap) item.Sep.Size = UDim2.fromOffset(self.Width - 25, 1) y = y + gap + 1 + gap else y = y + gap end end else item.Frame.Visible = false if item.Sep then item.Sep.Visible = false end end end self.Height = y if self.OnResize then self.OnResize(y) end end function Container:Add(frame, height) local item = { Frame = frame, Height = height, Visible = true } self.Items[#self.Items + 1] = item frame.Parent = self.Holder self:Update() return item end local function register(opts, obj) if opts.Flag then obj.Flag = opts.Flag Lycan.Flags[opts.Flag] = obj.Value Lycan.Options[opts.Flag] = obj end end local function noteName(self, name) if self.Tab then self.Tab.Names[#self.Tab.Names + 1] = tostring(name):lower() end end -- toggle function Container:Toggle(o) o = o or {} local obj = { Value = o.Default == true, Type = "Toggle" } local container = self -- obj methods shadow self local w = self.Width noteName(self, o.Name) local row = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 13) }) local box = create("Frame", { Parent = row, Size = UDim2.fromOffset(13, 13), BackgroundColor3 = T.Box, BorderSizePixel = 0 }, { corner(2) }) local check = create("ImageLabel", { Parent = box, BackgroundTransparency = 1, Position = UDim2.fromOffset(2, 2), Size = UDim2.fromOffset(10, 10), Image = asset("check_icon"), ImageColor3 = T.OnAccent, ImageTransparency = 1 }) local label = makeLabel(row, o.Name or "Toggle", 25, 6.6, T.Muted) local chevron = create("ImageButton", { Parent = row, BackgroundTransparency = 1, AutoButtonColor = false, Position = UDim2.fromOffset(w - 13, 0), Size = UDim2.fromOffset(13, 13), Image = asset("expand_up"), ImageColor3 = T.Muted, Visible = false }) local hit = create("TextButton", { Parent = row, BackgroundTransparency = 1, Text = "", AutoButtonColor = false, Size = UDim2.fromOffset(25, 13) }) connect(label:GetPropertyChangedSignal("AbsoluteSize"), function() hit.Size = UDim2.fromOffset(25 + label.AbsoluteSize.X / UIScale.Scale + 4, 13) end) local anim, hover = 0, 0 local function paint() local base = lerpColor(T.Box, T.Accent, anim) box.BackgroundColor3 = lerpColor(base, T.BoxHover, hover * (1 - anim)) check.ImageTransparency = 1 - anim label.TextColor3 = lerpColor(T.Muted, T.White, math.max(anim, hover * 0.35)) chevron.ImageColor3 = lerpColor(T.Muted, T.White, anim) end local animState = animated(0, function(v) anim = v paint() end, Window.Cleanup) local hoverState = animated(0, function(v) hover = v paint() end, Window.Cleanup) local item = self:Add(row, 13) function obj:Set(v, silent) v = v == true self.Value = v animState.To(v and 1 or 0, DUR.controls) if self.Flag then Lycan.Flags[self.Flag] = v end if not silent then safe(o.Callback, v) end end connect(hit.MouseButton1Click, function() obj:Set(not obj.Value) end) connect(hit.MouseEnter, function() hoverState.To(1, DUR.hover) end) connect(hit.MouseLeave, function() hoverState.To(0, DUR.hover) end) -- chevron opens a nested group under the row local drawer, open, expand function obj:Settings() if drawer then return drawer end chevron.Visible = true local holder = create("Frame", { Parent = row, BackgroundTransparency = 1, Position = UDim2.fromOffset(25, 13 + 12), Size = UDim2.fromOffset(w - 25, 0), ClipsDescendants = true, Visible = false }) -- keep the row in sync when the drawer resizes drawer = newContainer(holder, w - 25, true, function(h) if open then holder.Size = UDim2.fromOffset(w - 25, h) item.Height = 13 + 12 + h container:Update() end end) drawer.Tab = container.Tab expand = animated(0, function(a) holder.Visible = a > 0.001 holder.Size = UDim2.fromOffset(w - 25, drawer.Height * a) item.Height = 13 + (12 + drawer.Height) * a chevron.Rotation = 90 * a container:Update() end, Window.Cleanup) connect(chevron.MouseButton1Click, function() open = not open expand.To(open and 1 or 0, DUR.lists) end) return drawer end register(o, obj) if obj.Value then animState.Set(1) end return obj end -- slider function Container:Slider(o) o = o or {} local min, max, inc = o.Min or 0, o.Max or 100, o.Increment or 1 local obj = { Value = math.clamp(o.Default or min, min, max), Type = "Slider" } local w = self.Width noteName(self, o.Name) local row = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 30) }) local label = makeLabel(row, o.Name or "Slider", 0, 6.6, T.Muted) local valueLabel = makeLabel(row, "", w, 6.6, T.Muted, "Right") local track = create("Frame", { Parent = row, Position = UDim2.fromOffset(0, 20), Size = UDim2.fromOffset(w, 5), BackgroundColor3 = T.Box, BorderSizePixel = 0 }, { corner(100) }) local fill = create("Frame", { Parent = track, Size = UDim2.fromScale(0, 1), BackgroundColor3 = T.Accent, BorderSizePixel = 0 }, { corner(100) }) local knob = create("Frame", { Parent = track, AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.new(0, 0, 0.5, 0), Size = UDim2.fromOffset(9, 9), BackgroundColor3 = T.White, BorderSizePixel = 0, BackgroundTransparency = 1 }, { corner(100) }) local hit = create("TextButton", { Parent = row, BackgroundTransparency = 1, Text = "", AutoButtonColor = false, Position = UDim2.fromOffset(0, 14), Size = UDim2.fromOffset(w, 17) }) local shown = (obj.Value - min) / (max - min) local decimals = 0 do local s = tostring(inc) local dot = s:find("%.") if dot then decimals = #s - dot end end local function fmt(v) return (decimals > 0 and string.format("%." .. decimals .. "f", v) or tostring(math.floor(v + 0.5))) .. (o.Suffix or "") end local hoverAmt = 0 local function paint() fill.Size = UDim2.fromScale(math.clamp(shown, 0, 1), 1) knob.Position = UDim2.new(math.clamp(shown, 0, 1), 0, 0.5, 0) knob.BackgroundTransparency = 1 - hoverAmt valueLabel.TextColor3 = lerpColor(T.Muted, T.White, hoverAmt) label.TextColor3 = lerpColor(T.Muted, T.White, hoverAmt * 0.35) end local hv = animated(0, function(v) hoverAmt = v paint() end, Window.Cleanup) local shownAnim = animated(shown, function(v) shown = v paint() end, Window.Cleanup) self:Add(row, 30) function obj:Set(v, silent) v = math.clamp(tonumber(v) or min, min, max) v = math.floor((v - min) / inc + 0.5) * inc + min v = math.clamp(v, min, max) self.Value = v valueLabel.Text = fmt(v) shownAnim.To((v - min) / (max - min), DUR.controls) if self.Flag then Lycan.Flags[self.Flag] = v end if not silent then safe(o.Callback, v) end end local dragging = false local function fromInput(input) local pos = pointerPosition(input) local a = math.clamp((pos.X - track.AbsolutePosition.X) / math.max(1, track.AbsoluteSize.X), 0, 1) obj:Set(min + (max - min) * a, o.OnRelease) -- OnRelease: the callback waits for the mouse up end connect(hit.InputBegan, function(input) if inputIsPress(input) then dragging = true hv.To(1, DUR.hover) fromInput(input) end end) connect(hit.MouseEnter, function() hv.To(1, DUR.hover) end) connect(hit.MouseLeave, function() if not dragging then hv.To(0, DUR.hover) end end) connect(UserInputService.InputChanged, function(input) if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then fromInput(input) end end) connect(UserInputService.InputEnded, function(input) if dragging and inputIsPress(input) then dragging = false hv.To(0, DUR.hover) if o.OnRelease then safe(o.Callback, obj.Value) end end end) valueLabel.Text = fmt(obj.Value) shownAnim.Set((obj.Value - min) / (max - min)) register(o, obj) return obj end -- popup panel under an anchor (dropdown list, color picker) local function openPanel(anchor, width, height, build) closePopup() local startPos = overlayPos(anchor.AbsolutePosition) local aSize = anchor.AbsoluteSize / UIScale.Scale local x = math.clamp(startPos.X, 0, W - width) local frame = create("Frame", { Parent = Overlay, BackgroundColor3 = T.List, BackgroundTransparency = T.ListTr, Position = UDim2.fromOffset(x, startPos.Y + aSize.Y + 6), Size = UDim2.fromOffset(width, height), BorderSizePixel = 0, ZIndex = 60 }, { corner(6) }) create("UIStroke", { Parent = frame, Color = T.ListStroke, Transparency = T.ListStrokeTr, Thickness = 1 }) local mine = {} scope = mine build(frame) scope = nil presentPopup(frame, anchor, mine) return frame end -- dropdown function Container:Dropdown(o) o = o or {} local options = o.Options or {} local multi = o.Multi == true local obj = { Type = "Dropdown", Options = options } if multi then obj.Value = {} for _, v in ipairs(o.Default or {}) do obj.Value[v] = true end else obj.Value = o.Default or options[1] end local w = self.Width noteName(self, o.Name) local row = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 49) }) local label = makeLabel(row, o.Name or "Dropdown", 0, 6.6, T.Muted) local box = create("TextButton", { Parent = row, AutoButtonColor = false, Text = "", Position = UDim2.fromOffset(0, 21), Size = UDim2.fromOffset(w, 28), BackgroundColor3 = T.Box, BorderSizePixel = 0, ClipsDescendants = true }, { corner(6) }) local valueText = makeLabel(box, "", 10, 14, T.Hover) local arrow = create("ImageLabel", { Parent = box, BackgroundTransparency = 1, Position = UDim2.fromOffset(w - 22, 8), Size = UDim2.fromOffset(13, 13), Image = asset("arrow"), ImageColor3 = T.Muted }) valueText.Size = UDim2.fromOffset(w - 40, 14) valueText.AutomaticSize = Enum.AutomaticSize.None valueText.TextTruncate = Enum.TextTruncate.AtEnd local hv = animated(0, function(a) box.BackgroundColor3 = lerpColor(T.Box, T.BoxHover, a * 0.5) label.TextColor3 = lerpColor(T.Muted, T.White, a * 0.35) end, Window.Cleanup) connect(box.MouseEnter, function() hv.To(1, DUR.hover) end) connect(box.MouseLeave, function() hv.To(0, DUR.hover) end) local function text() if multi then local names = {} for _, opt in ipairs(options) do if obj.Value[opt] then names[#names + 1] = opt end end return #names > 0 and table.concat(names, ", ") or "None" end return tostring(obj.Value or "None") end self:Add(row, 49) function obj:Set(v, silent) if multi then local t = {} if type(v) == "table" then for k, val in pairs(v) do if type(k) == "number" then t[val] = true elseif val then t[k] = true end end end self.Value = t else self.Value = v end valueText.Text = text() if self.Flag then Lycan.Flags[self.Flag] = self.Value end if not silent then safe(o.Callback, self.Value) end end function obj:SetOptions(list) options = list self.Options = list if not multi and self.Value == nil then self:Set(list[1], true) end end connect(box.MouseButton1Click, function() if activePopup and activePopup.anchor == box then closePopup() return end local rowH, shownRows = 28, math.min(#options, 7) tween(arrow, { Rotation = 180 }, DUR.lists) local panel = openPanel(box, w, rowH * shownRows, function(frame) local scroll = create("ScrollingFrame", { Parent = frame, BackgroundTransparency = 1, BorderSizePixel = 0, Size = UDim2.fromScale(1, 1), CanvasSize = UDim2.fromOffset(0, rowH * #options), ScrollBarThickness = 0, ZIndex = 61 }) for i, opt in ipairs(options) do local rowBtn = create("TextButton", { Parent = scroll, AutoButtonColor = false, Text = "", BackgroundTransparency = 1, Position = UDim2.fromOffset(0, (i - 1) * rowH), Size = UDim2.fromOffset(w, rowH), ZIndex = 61 }) local rowHover = create("Frame", { Parent = rowBtn, Position = UDim2.fromOffset(3, 3), Size = UDim2.new(1, -6, 1, -6), BackgroundColor3 = T.White, BackgroundTransparency = 1, BorderSizePixel = 0, ZIndex = 61 }, { corner(3) }) local active = multi and obj.Value[opt] or (not multi and obj.Value == opt) local txt = makeLabel(rowBtn, tostring(opt), 12, rowH / 2, active and T.ListActive or T.Muted) txt.ZIndex = 62 connect(rowBtn.MouseEnter, function() tween(rowHover, { BackgroundTransparency = 1 - 12 / 255 }, DUR.hover) tween(txt, { TextColor3 = T.ListActive }, DUR.hover) end) connect(rowBtn.MouseLeave, function() tween(rowHover, { BackgroundTransparency = 1 }, DUR.hover) local on = multi and obj.Value[opt] or (not multi and obj.Value == opt) tween(txt, { TextColor3 = on and T.ListActive or T.Muted }, DUR.hover) end) connect(rowBtn.MouseButton1Click, function() if multi then local t = table.clone(obj.Value) t[opt] = not t[opt] or nil obj:Set(t) else obj:Set(opt) closePopup() end end) end end) local prevClose = activePopup.close activePopup.close = function() tween(arrow, { Rotation = 0 }, DUR.lists) prevClose() end end) valueText.Text = text() register(o, obj) return obj end -- keybind function Container:Keybind(o) o = o or {} local obj = { Value = o.Default, Type = "Keybind" } local w = self.Width noteName(self, o.Name) local row = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 17) }) local label = makeLabel(row, o.Name or "Keybind", 0, 8.5, T.Muted) local pill = create("TextButton", { Parent = row, AutoButtonColor = false, Text = "", AnchorPoint = Vector2.new(1, 0.5), Position = UDim2.fromOffset(w, 8.5), Size = UDim2.fromOffset(40, 17), AutomaticSize = Enum.AutomaticSize.X, BackgroundColor3 = T.Box, BorderSizePixel = 0 }, { corner(4), create("UIPadding", { PaddingLeft = UDim.new(0, 8), PaddingRight = UDim.new(0, 8) }) }) local keyText = create("TextLabel", { Parent = pill, BackgroundTransparency = 1, Size = UDim2.fromOffset(0, 17), AutomaticSize = Enum.AutomaticSize.X, FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Muted, Text = "None" }) local waiting = 0 local hover = 0 local function paint() pill.BackgroundColor3 = lerpColor(lerpColor(T.Box, T.BoxHover, hover * 0.5), T.Accent, waiting * 0.15) keyText.TextColor3 = lerpColor(T.Muted, T.White, math.max(waiting, hover * 0.5)) label.TextColor3 = lerpColor(T.Muted, T.White, hover * 0.35) end local waitAnim = animated(0, function(v) waiting = v paint() end, Window.Cleanup) local hoverAnim = animated(0, function(v) hover = v paint() end, Window.Cleanup) connect(pill.MouseEnter, function() hoverAnim.To(1, DUR.hover) end) connect(pill.MouseLeave, function() hoverAnim.To(0, DUR.hover) end) self:Add(row, 17) function obj:Set(k, silent) if typeof(k) == "string" then k = Enum.KeyCode[k] end self.Value = k keyText.Text = k and k.Name or "None" if self.Flag then Lycan.Flags[self.Flag] = k end end local listening = false connect(pill.MouseButton1Click, function() if listening then return end listening = true keyText.Text = "..." waitAnim.To(1, DUR.controls) local conn conn = UserInputService.InputBegan:Connect(function(input) if input.UserInputType ~= Enum.UserInputType.Keyboard then return end conn:Disconnect() listening = false waitAnim.To(0, DUR.controls) if input.KeyCode == Enum.KeyCode.Escape then obj:Set(nil) else obj:Set(input.KeyCode) end safe(o.Changed, obj.Value) end) end) connect(UserInputService.InputBegan, function(input, processed) if listening or processed or not obj.Value or input.UserInputType ~= Enum.UserInputType.Keyboard then return end if input.KeyCode == obj.Value then safe(o.Callback, obj.Value) end end) if o.Mode == "Hold" then connect(UserInputService.InputEnded, function(input) if obj.Value and input.KeyCode == obj.Value and o.Released then safe(o.Released, obj.Value) end end) end obj:Set(obj.Value, true) register(o, obj) return obj end -- color picker function Container:ColorPicker(o) o = o or {} local obj = { Value = o.Default or T.White, Type = "ColorPicker" } local w = self.Width noteName(self, o.Name) local row = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 13) }) local label = makeLabel(row, o.Name or "Color", 0, 6.6, T.Muted) local swatch = create("TextButton", { Parent = row, AutoButtonColor = false, Text = "", AnchorPoint = Vector2.new(1, 0), Position = UDim2.fromOffset(w, 0), Size = UDim2.fromOffset(24, 13), BackgroundColor3 = obj.Value, BorderSizePixel = 0 }, { corner(3), create("UIStroke", { Color = T.ListStroke, Transparency = 1 - 30 / 255, Thickness = 1 }) }) self:Add(row, 13) local h, s, v = obj.Value:ToHSV() function obj:Set(c, silent) self.Value = c h, s, v = c:ToHSV() swatch.BackgroundColor3 = c if self.Flag then Lycan.Flags[self.Flag] = c end if self.Refresh then self.Refresh() end if not silent then safe(o.Callback, c) end end connect(swatch.MouseEnter, function() tween(label, { TextColor3 = T.Hover }, DUR.hover) end) connect(swatch.MouseLeave, function() tween(label, { TextColor3 = T.Muted }, DUR.hover) end) connect(swatch.MouseButton1Click, function() if activePopup and activePopup.anchor == swatch then closePopup() return end openPanel(swatch, 196, 168, function(frame) local pad = 10 local svW, svH = 176, 96 local sv = create("Frame", { Parent = frame, Position = UDim2.fromOffset(pad, pad), Size = UDim2.fromOffset(svW, svH), BackgroundColor3 = Color3.fromHSV(h, 1, 1), BorderSizePixel = 0, ZIndex = 61 }, { corner(4) }) local white = create("Frame", { Parent = sv, Size = UDim2.fromScale(1, 1), BackgroundColor3 = T.White, BorderSizePixel = 0, ZIndex = 62 }, { corner(4), create("UIGradient", { Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0), NumberSequenceKeypoint.new(1, 1) }) }) }) local black = create("Frame", { Parent = sv, Size = UDim2.fromScale(1, 1), BackgroundColor3 = rgb(0, 0, 0), BorderSizePixel = 0, ZIndex = 63 }, { corner(4), create("UIGradient", { Rotation = 90, Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 1), NumberSequenceKeypoint.new(1, 0) }) }) }) local cursor = create("Frame", { Parent = sv, AnchorPoint = Vector2.new(0.5, 0.5), Size = UDim2.fromOffset(8, 8), BackgroundTransparency = 1, BorderSizePixel = 0, ZIndex = 64 }, { corner(100), create("UIStroke", { Color = T.White, Thickness = 1.5 }) }) local hue = create("Frame", { Parent = frame, Position = UDim2.fromOffset(pad, pad + svH + 10), Size = UDim2.fromOffset(svW, 8), BackgroundColor3 = T.White, BorderSizePixel = 0, ZIndex = 61 }, { corner(100), create("UIGradient", { Color = ColorSequence.new({ ColorSequenceKeypoint.new(0, rgb(255, 0, 0)), ColorSequenceKeypoint.new(1 / 6, rgb(255, 255, 0)), ColorSequenceKeypoint.new(2 / 6, rgb(0, 255, 0)), ColorSequenceKeypoint.new(3 / 6, rgb(0, 255, 255)), ColorSequenceKeypoint.new(4 / 6, rgb(0, 0, 255)), ColorSequenceKeypoint.new(5 / 6, rgb(255, 0, 255)), ColorSequenceKeypoint.new(1, rgb(255, 0, 0)) }) }) }) local hueKnob = create("Frame", { Parent = hue, AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0, 0.5), Size = UDim2.fromOffset(10, 10), BackgroundColor3 = T.White, BorderSizePixel = 0, ZIndex = 62 }, { corner(100) }) local hex = create("TextBox", { Parent = frame, Position = UDim2.fromOffset(pad, pad + svH + 28), Size = UDim2.fromOffset(svW, 20), BackgroundColor3 = T.Box, BorderSizePixel = 0, FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Text, Text = "", ClearTextOnFocus = false, ZIndex = 61 }, { corner(4) }) local function refresh() sv.BackgroundColor3 = Color3.fromHSV(h, 1, 1) cursor.Position = UDim2.fromScale(s, 1 - v) hueKnob.Position = UDim2.fromScale(h, 0.5) hex.Text = "#" .. obj.Value:ToHex():upper() end obj.Refresh = refresh local function apply() local c = Color3.fromHSV(h, s, v) obj.Value = c swatch.BackgroundColor3 = c if obj.Flag then Lycan.Flags[obj.Flag] = c end refresh() safe(o.Callback, c) end refresh() local dragSV, dragHue = false, false local function moveSV(input) local p = pointerPosition(input) s = math.clamp((p.X - sv.AbsolutePosition.X) / math.max(1, sv.AbsoluteSize.X), 0, 1) v = 1 - math.clamp((p.Y - sv.AbsolutePosition.Y) / math.max(1, sv.AbsoluteSize.Y), 0, 1) apply() end local function moveHue(input) local p = pointerPosition(input) h = math.clamp((p.X - hue.AbsolutePosition.X) / math.max(1, hue.AbsoluteSize.X), 0, 0.999) apply() end local b1 = create("TextButton", { Parent = sv, Text = "", BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1), ZIndex = 65, AutoButtonColor = false }) local b2 = create("TextButton", { Parent = hue, Text = "", BackgroundTransparency = 1, Size = UDim2.new(1, 0, 1, 8), Position = UDim2.fromOffset(0, -4), ZIndex = 65, AutoButtonColor = false }) local c1 = b1.InputBegan:Connect(function(i) if inputIsPress(i) then dragSV = true moveSV(i) end end) local c2 = b2.InputBegan:Connect(function(i) if inputIsPress(i) then dragHue = true moveHue(i) end end) local c3 = UserInputService.InputChanged:Connect(function(i) if i.UserInputType ~= Enum.UserInputType.MouseMovement and i.UserInputType ~= Enum.UserInputType.Touch then return end if dragSV then moveSV(i) elseif dragHue then moveHue(i) end end) local c4 = UserInputService.InputEnded:Connect(function(i) if inputIsPress(i) then dragSV, dragHue = false, false end end) hex.FocusLost:Connect(function() local okc, c = pcall(Color3.fromHex, hex.Text) if okc then obj:Set(c) else refresh() end end) frame.Destroying:Connect(function() obj.Refresh = nil c1:Disconnect() c2:Disconnect() c3:Disconnect() c4:Disconnect() end) end) end) register(o, obj) return obj end -- textbox function Container:Textbox(o) o = o or {} local obj = { Value = o.Default or "", Type = "Textbox" } local w = self.Width noteName(self, o.Name) local row = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 49) }) local label = makeLabel(row, o.Name or "Textbox", 0, 6.6, T.Muted) local box = create("Frame", { Parent = row, Position = UDim2.fromOffset(0, 21), Size = UDim2.fromOffset(w, 28), BackgroundColor3 = T.Box, BorderSizePixel = 0 }, { corner(6) }) local stroke = create("UIStroke", { Parent = box, Color = T.White, Transparency = 1, Thickness = 1 }) local input = create("TextBox", { Parent = box, BackgroundTransparency = 1, Position = UDim2.fromOffset(10, 0), Size = UDim2.fromOffset(w - 20, 28), FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Text, PlaceholderText = o.Placeholder or "", PlaceholderColor3 = T.Muted, Text = obj.Value, ClearTextOnFocus = false, TextXAlignment = Enum.TextXAlignment.Left, ClipsDescendants = true }) local focus = animated(0, function(a) stroke.Transparency = 1 - 0.35 * a label.TextColor3 = lerpColor(T.Muted, T.White, a * 0.5) end, Window.Cleanup) connect(input.Focused, function() focus.To(1, DUR.controls) end) connect(input.FocusLost, function() focus.To(0, DUR.controls) obj.Value = input.Text if obj.Flag then Lycan.Flags[obj.Flag] = obj.Value end safe(o.Callback, obj.Value) end) self:Add(row, 49) function obj:Set(v, silent) self.Value = tostring(v) input.Text = self.Value if self.Flag then Lycan.Flags[self.Flag] = self.Value end if not silent then safe(o.Callback, self.Value) end end register(o, obj) return obj end -- button function Container:Button(o) o = o or {} local obj = { Type = "Button" } local w = self.Width noteName(self, o.Name) local btn = create("TextButton", { AutoButtonColor = false, Text = "", Size = UDim2.fromOffset(w, 28), BackgroundColor3 = T.Panel, BackgroundTransparency = T.PanelTr, BorderSizePixel = 0 }, { corner(6) }) local text = create("TextLabel", { Parent = btn, BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1), FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Hover, Text = o.Name or "Button" }) local hover, press = 0, 0 local function paint() btn.BackgroundColor3 = lerpColor(lerpColor(T.Panel, T.PanelHover, hover), T.PanelPress, press) text.TextColor3 = lerpColor(T.Hover, T.White, hover) end local hv = animated(0, function(a) hover = a paint() end, Window.Cleanup) local pr = animated(0, function(a) press = a paint() end, Window.Cleanup) connect(btn.MouseEnter, function() hv.To(1, DUR.hover) end) connect(btn.MouseLeave, function() hv.To(0, DUR.hover) pr.To(0, DUR.press) end) connect(btn.MouseButton1Down, function() pr.To(1, DUR.press) end) connect(btn.MouseButton1Up, function() pr.To(0, DUR.press) end) connect(btn.MouseButton1Click, function() safe(o.Callback) end) self:Add(btn, 28) function obj:SetText(t) text.Text = t end return obj end -- label / paragraph function Container:Label(o) o = type(o) == "string" and { Text = o } or (o or {}) local obj = { Type = "Label" } local w = self.Width local text = create("TextLabel", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 13), FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Muted, Text = o.Text or o.Name or "", TextXAlignment = Enum.TextXAlignment.Left, TextWrapped = true, AutomaticSize = Enum.AutomaticSize.Y }) local item = self:Add(text, 13) connect(text:GetPropertyChangedSignal("AbsoluteSize"), function() local h = math.max(13, text.AbsoluteSize.Y / UIScale.Scale) if math.abs(item.Height - h) > 0.5 then item.Height = h self:Update() end end) function obj:Set(t) text.Text = t end return obj end function Container:Paragraph(o) o = o or {} local obj = { Type = "Paragraph" } local w = self.Width local holder = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(w, 30) }) makeLabel(holder, o.Title or o.Name or "", 0, 6.6, T.White) local body = create("TextLabel", { Parent = holder, BackgroundTransparency = 1, Position = UDim2.fromOffset(0, 18), Size = UDim2.fromOffset(w, 12), FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Muted, Text = o.Content or "", TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, TextWrapped = true, AutomaticSize = Enum.AutomaticSize.Y }) local item = self:Add(holder, 30) connect(body:GetPropertyChangedSignal("AbsoluteSize"), function() local h = 18 + math.max(12, body.AbsoluteSize.Y / UIScale.Scale) if math.abs(item.Height - h) > 0.5 then item.Height = h holder.Size = UDim2.fromOffset(w, h) self:Update() end end) function obj:Set(t) body.Text = t end return obj end -- page / section local Page = {} Page.__index = Page local Section = {} Section.__index = Section setmetatable(Section, { __index = Container }) local COL_X = { Left = 0, Right = 275 } local function buildPage(tab, name) local group = create("Frame", { Name = "Page_" .. name, Parent = content, BackgroundTransparency = 1, Position = UDim2.fromOffset(15, 90), Size = UDim2.fromOffset(560, 373), Visible = false, ClipsDescendants = true }) local scroll = create("ScrollingFrame", { Parent = group, BackgroundTransparency = 1, BorderSizePixel = 0, Size = UDim2.fromScale(1, 1), CanvasSize = UDim2.fromOffset(0, 0), ScrollBarThickness = 0, ScrollingDirection = Enum.ScrollingDirection.Y, ElasticBehavior = Enum.ElasticBehavior.Never }) local track = create("Frame", { Name = "Track", Parent = group, Position = UDim2.fromOffset(550, 0), Size = UDim2.fromOffset(10, 373), BackgroundColor3 = T.Panel, BackgroundTransparency = T.PanelTr, BorderSizePixel = 0, Visible = false }) local thumb = create("Frame", { Parent = track, Size = UDim2.fromOffset(10, 100), BackgroundColor3 = T.Accent, BorderSizePixel = 0 }, { corner(100) }) local page = setmetatable({ Tab = tab, Name = name, Group = group, Scroll = scroll, Sections = {}, Cols = { Left = 0, Right = 0 } }, Page) function page:Update() local cols = { Left = 0, Right = 0 } for _, sec in ipairs(self.Sections) do local c = cols[sec.Side] sec.TitleLabel.Position = UDim2.fromOffset(COL_X[sec.Side], c - 3) sec.Card.Position = UDim2.fromOffset(COL_X[sec.Side], c + 17) cols[sec.Side] = c + 17 + sec.Card.Size.Y.Offset + 9 end local bottom = math.max(cols.Left, cols.Right) - 9 + 15 scroll.CanvasSize = UDim2.fromOffset(0, math.max(bottom, 0)) self.Cols = cols self:UpdateBar() end function page:UpdateBar() local view = 373 local canvas = scroll.AbsoluteCanvasSize.Y / math.max(UIScale.Scale, 0.01) if canvas <= view + 1 then track.Visible = false return end track.Visible = true local ratio = view / canvas local th = math.max(24, 373 * ratio) local maxScroll = canvas - view local pos = (scroll.CanvasPosition.Y / math.max(maxScroll, 1)) * (373 - th) thumb.Size = UDim2.fromOffset(10, th) thumb.Position = UDim2.fromOffset(0, math.clamp(pos, 0, 373 - th)) end connect(scroll:GetPropertyChangedSignal("CanvasPosition"), function() page:UpdateBar() end) connect(scroll:GetPropertyChangedSignal("AbsoluteCanvasSize"), function() page:UpdateBar() end) -- scrollbar thumb drag local dragging, startY, startCanvas connect(thumb.InputBegan, function(input) if inputIsPress(input) then dragging, startY, startCanvas = true, pointerPosition(input).Y, scroll.CanvasPosition.Y end end) connect(UserInputService.InputChanged, function(input) if not dragging then return end if input.UserInputType ~= Enum.UserInputType.MouseMovement and input.UserInputType ~= Enum.UserInputType.Touch then return end local canvas = scroll.AbsoluteCanvasSize.Y / math.max(UIScale.Scale, 0.01) local view = 373 local th = math.max(24, 373 * view / canvas) local dy = (pointerPosition(input).Y - startY) / UIScale.Scale scroll.CanvasPosition = Vector2.new(0, startCanvas + dy * (canvas - view) / math.max(373 - th, 1)) end) connect(UserInputService.InputEnded, function(input) if dragging and inputIsPress(input) then dragging = false end end) return page end function Tab:Page(popts) popts = type(popts) == "string" and { Name = popts } or (popts or {}) local page = buildPage(self, popts.Name or "Main") self.Pages[#self.Pages + 1] = page if not self.CurrentPage then self.CurrentPage = page end if self.PendingSelect then self.PendingSelect = nil task.defer(function() selectTab(self, true) end) end return page end function Page:Section(sopts) sopts = type(sopts) == "string" and { Name = sopts } or (sopts or {}) local side = sopts.Side == "Right" and "Right" or (sopts.Side == "Left" and "Left") if not side then side = self.Cols.Left <= self.Cols.Right and "Left" or "Right" end local titleLabel = makeLabel(self.Scroll, sopts.Name or "Section", 0, 0, T.Muted) local card = create("Frame", { Parent = self.Scroll, Size = UDim2.fromOffset(260, 24), BackgroundColor3 = T.Panel, BackgroundTransparency = T.PanelTr, BorderSizePixel = 0 }, { corner(8) }) local holder = create("Frame", { Parent = card, BackgroundTransparency = 1, Position = UDim2.fromOffset(12, 12), Size = UDim2.fromOffset(236, 0) }) local sec = setmetatable({ Page = self, Side = side, TitleLabel = titleLabel, Card = card, Tab = self.Tab }, Section) local c = newContainer(holder, 236, false, function(h) holder.Size = UDim2.fromOffset(236, h) card.Size = UDim2.fromOffset(260, h + 24) self:Update() end) c.Tab = self.Tab -- section is its own container, reuse the fields sec.Holder, sec.Width, sec.Compact, sec.Items, sec.Height, sec.OnResize = c.Holder, c.Width, c.Compact, c.Items, 0, c.OnResize self.Sections[#self.Sections + 1] = sec sec:Update() return sec end -- no page made = default page called Main function Tab:Section(sopts) local page = self.CurrentPage or self:Page({ Name = self.PageName or "Main" }) return page:Section(sopts) end -- search (filters tabs by tab / control name) connect(searchBox:GetPropertyChangedSignal("Text"), function() local q = searchBox.Text:lower() for _, tab in ipairs(Window.Tabs) do local match = q == "" if not match then if tab.Name:lower():find(q, 1, true) then match = true end if not match then for _, n in ipairs(tab.Names) do if n:find(q, 1, true) then match = true break end end end end tab.Match = match end layoutNav(true) end) -- built in popups: configs (left button), settings (right button) local function popupContainer(anchor, width, title, buildFn) closePopup() local h = 0 local startPos = overlayPos(anchor.AbsolutePosition) local aSize = anchor.AbsoluteSize / UIScale.Scale local x = math.clamp(startPos.X + (anchor == settingsButton and aSize.X - width or 0), 0, W - width) local frame = create("Frame", { Parent = Overlay, BackgroundColor3 = T.List, BackgroundTransparency = T.ListTr, Position = UDim2.fromOffset(x, startPos.Y + aSize.Y + 6), Size = UDim2.fromOffset(width, 40), BorderSizePixel = 0, ZIndex = 60 }, { corner(8) }) create("UIStroke", { Parent = frame, Color = T.ListStroke, Transparency = T.ListStrokeTr, Thickness = 1 }) makeLabel(frame, title, 12, 18, T.White).ZIndex = 61 local holder = create("Frame", { Parent = frame, BackgroundTransparency = 1, Position = UDim2.fromOffset(12, 36), Size = UDim2.fromOffset(width - 24, 0), ZIndex = 61 }) local cont = newContainer(holder, width - 24, true, function(ch) holder.Size = UDim2.fromOffset(width - 24, ch) frame.Size = UDim2.fromOffset(width, ch + 36 + 12) end) cont.Tab = nil local mine = {} scope = mine buildFn(cont) cont:Update() scope = nil for _, d in ipairs(frame:GetDescendants()) do if d:IsA("GuiObject") then d.ZIndex = math.max(d.ZIndex, 61) end end presentPopup(frame, anchor, mine) end Window.OnLeftButton = nil connect(leftButton.MouseButton1Click, function() if activePopup and activePopup.anchor == leftButton then closePopup() return end if Window.OnLeftButton then safe(Window.OnLeftButton) return end popupContainer(leftButton, 220, "Configs", function(cont) local name = "default" cont:Textbox({ Name = "Config name", Default = name, Callback = function(t) name = t end }) cont:Button({ Name = "Save", Callback = function() local ok = Lycan:SaveConfig(name) Window:Notify({ Title = "Config", Content = ok and ("saved " .. name) or "executor can't write files", Type = ok and "success" or "error" }) end }) cont:Button({ Name = "Load", Callback = function() local ok = Lycan:LoadConfig(name) Window:Notify({ Title = "Config", Content = ok and ("loaded " .. name) or ("no config named " .. name), Type = ok and "success" or "warning" }) end }) -- listfiles can be slow, so the list fills in after the popup is already open local saved = cont:Label({ Text = "" }) task.spawn(function() local list = Lycan:ListConfigs() saved:Set(#list > 0 and ("saved: " .. table.concat(list, ", ")) or "no saved configs") end) end) end) connect(settingsButton.MouseButton1Click, function() if activePopup and activePopup.anchor == settingsButton then closePopup() return end popupContainer(settingsButton, 220, "Settings", function(cont) cont:Toggle({ Name = "Background glow", Default = Window.Glow, Callback = function(v) Window:SetGlow(v) end }) cont:Slider({ Name = "Window opacity", Min = 30, Max = 100, Default = math.floor(Window.Opacity * 100 + 0.5), Suffix = "%", Callback = function(v) Window:SetOpacity(v / 100) end }) cont:Slider({ Name = "UI scale", Min = 50, Max = 150, Increment = 5, OnRelease = true, Default = math.floor(UIScale.Scale * 20 + 0.5) * 5, Suffix = "%", Callback = function(v) Window:SetScale(v / 100) end }) cont:Keybind({ Name = "Menu key", Default = Window.Keybind, Changed = function(k) if k then Window.Keybind = k end end }) cont:Button({ Name = "Unload", Callback = function() Window:Destroy() end }) end) end) -- toggle key + mobile button Window.Keybind = opts.Keybind or Enum.KeyCode.RightShift function Window:Toggle(state) if state == nil then state = not self.Toggled end self.Toggled = state Main.Visible = state if not state then closePopup() end end connect(UserInputService.InputBegan, function(input, processed) if processed then return end if input.UserInputType == Enum.UserInputType.Keyboard and input.KeyCode == Window.Keybind then Window:Toggle() end end) if Lycan.IsMobile or opts.MobileButton then local pill = create("TextButton", { Parent = gui, AutoButtonColor = false, Text = "", AnchorPoint = Vector2.new(0.5, 0), Position = UDim2.new(0.5, 0, 0, 12), Size = UDim2.fromOffset(40, 40), BackgroundColor3 = T.Side, BackgroundTransparency = 0.05, BorderSizePixel = 0 }, { corner(20), create("UIStroke", { Color = T.ListStroke, Transparency = T.ListStrokeTr }) }) create("ImageLabel", { Parent = pill, BackgroundTransparency = 1, AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), Size = UDim2.fromOffset(20, 20), Image = asset("logo_pill") }) connect(pill.MouseButton1Click, function() Window:Toggle() end) end -- notifications local toasts = create("Frame", { Name = "Toasts", Parent = gui, BackgroundTransparency = 1, AnchorPoint = Vector2.new(1, 1), Position = UDim2.new(1, -20, 1, -20), Size = UDim2.fromOffset(270, 400) }) create("UIListLayout", { Parent = toasts, FillDirection = Enum.FillDirection.Vertical, VerticalAlignment = Enum.VerticalAlignment.Bottom, HorizontalAlignment = Enum.HorizontalAlignment.Right, Padding = UDim.new(0, 10), SortOrder = Enum.SortOrder.LayoutOrder }) function Window:Notify(n) n = n or {} local duration = n.Duration or 4 local kindColor = ({ success = T.White, error = rgb(255, 120, 120), warning = rgb(255, 210, 120) })[n.Type] or T.White local wrapper = create("Frame", { Parent = toasts, BackgroundTransparency = 1, Size = UDim2.fromOffset(260, 0), AutomaticSize = Enum.AutomaticSize.Y }) -- the bar sits outside the list so it can stick to the bottom local card = create("Frame", { Parent = wrapper, Position = UDim2.fromOffset(280, 0), Size = UDim2.fromOffset(260, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundColor3 = T.List, BackgroundTransparency = T.ListTr, BorderSizePixel = 0, ClipsDescendants = true }, { corner(8), create("UIStroke", { Color = T.ListStroke, Transparency = T.ListStrokeTr, Thickness = 1 }), }) local body = create("Frame", { Parent = card, BackgroundTransparency = 1, Size = UDim2.fromOffset(260, 0), AutomaticSize = Enum.AutomaticSize.Y }, { create("UIPadding", { PaddingLeft = UDim.new(0, 12), PaddingRight = UDim.new(0, 12), PaddingTop = UDim.new(0, 11), PaddingBottom = UDim.new(0, 14) }), create("UIListLayout", { Padding = UDim.new(0, 4), SortOrder = Enum.SortOrder.LayoutOrder }), }) create("TextLabel", { Parent = body, LayoutOrder = 1, BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 13), FontFace = InterSemi, TextSize = TEXT, TextColor3 = kindColor, Text = n.Title or "Lycan", TextXAlignment = Enum.TextXAlignment.Left }) if n.Content and n.Content ~= "" then create("TextLabel", { Parent = body, LayoutOrder = 2, BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 12), AutomaticSize = Enum.AutomaticSize.Y, FontFace = InterMedium, TextSize = TEXT, TextColor3 = T.Muted, Text = n.Content, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, TextWrapped = true }) end -- inset and rounded, clipping ignores the card's corners so a flush bar sticks out past them local bar = create("Frame", { Parent = card, AnchorPoint = Vector2.new(0, 1), Position = UDim2.new(0, 12, 1, -7), Size = UDim2.new(1, -24, 0, 2), BackgroundColor3 = kindColor, BackgroundTransparency = 0.45, BorderSizePixel = 0, ZIndex = 3 }, { corner(100) }) tween(card, { Position = UDim2.fromOffset(0, 0) }, DUR.pages) tween(bar, { Size = UDim2.new(0, 0, 0, 2) }, duration, Enum.EasingStyle.Linear) task.delay(duration, function() if not card.Parent then return end tween(card, { Position = UDim2.fromOffset(280, 0) }, DUR.pages) task.wait(DUR.pages) wrapper:Destroy() end) end -- unload function Window:Destroy() closePopup() for _, c in ipairs(self.Cleanup) do pcall(function() c:Disconnect() end) end table.clear(self.Cleanup) gui:Destroy() if Lycan.Window == self then Lycan.Window = nil end end -- make sure the first tab shows even if no page was made task.defer(function() if not selectedTab and Window.Tabs[1] then local tab = Window.Tabs[1] if #tab.Pages == 0 then tab:Page({ Name = "Main" }) end selectTab(tab, true) end end) Lycan.Window = Window return Window end return Lycan