Noctro
Hard-coded · single file

noctro.lua

This is the exact file served at /noctro.lua , 4,984 lines, plain Luau, nothing minified or hidden behind a build step.

noctro.cc/noctro.lua
4,984 lines
1local CSK = ColorSequenceKeypoint.new
2local NSK = NumberSequenceKeypoint.new
3local BSP = Enum.BorderStrokePosition
4local ASM = Enum.ApplyStrokeMode
5local UFA = Enum.UIFlexAlignment
6local TXA = Enum.TextXAlignment
7local TYA = Enum.TextYAlignment
8local UIT = Enum.UserInputType
9local ETT = Enum.TextTruncate
10local UFO = UDim2.fromOffset
11local UFS = UDim2.fromScale
12local EGS = Enum.GuiState
13local EKC = Enum.KeyCode
14local TCC = table.concat
15local TIS = table.insert
16local TR = table.remove
17local TU = table.unpack
18local TC = table.clone
19local TF = table.find
20local MC = math.clamp
21local MR = math.round
22local MF = math.floor
23local MM = math.min
24local MH = math.huge
25local ED = Enum.EasingDirection
26local AS = Enum.AutomaticSize
27local FD = Enum.FillDirection
28local ES = Enum.EasingStyle
29local FW = Enum.FontWeight
30local SO = Enum.SortOrder
31local FS = Enum.FontStyle
32local EF = Enum.Font
33local TI = TweenInfo.new
34local SF = string.format
35local V2 = Vector2.new
36local UD2 = UDim2.new
37local UD = UDim.new
38local FN = Font.new
39local RGB = Color3.fromRGB
40local HSV = Color3.fromHSV
41local CS = ColorSequence.new
42local NS = NumberSequence.new
43local SCT = Enum.SizeConstraint
44local SCL = Enum.ScaleType
45local ZIB = Enum.ZIndexBehavior
46local AT = Enum.AutomaticSize
47local HFA = Enum.HorizontalAlignment
48local VFA = Enum.VerticalAlignment
49local LC = Enum.LineJoinMode
50local SBD = Enum.ScrollingDirection
51local SBA = Enum.ScrollBarInset
52
53local Library = {
54 Elements = {};
55 SubElements = {};
56
57 Flags = {};
58 Threads = {};
59
60 Searchable = {};
61 Sections = {};
62}
63
64Library.__index = Library
65Library.Elements.__index = Library.Elements
66Library.SubElements.__index = Library.SubElements
67
68local PopupZ = 20
69
70cloneref = cloneref or function(...) return ... end
71gethui = gethui or function(...) return cloneref(game:GetService("CoreGui")) end
72
73local Services = {
74 GetService = function(self, service)
75 return cloneref(game:GetService(service))
76 end,
77} :: ServiceProvider
78
79local UserInputService = Services:GetService("UserInputService")
80local PlayerService = Services:GetService("Players")
81local RunService = Services:GetService("RunService")
82local TweenService = Services:GetService("TweenService")
83
84local Client = PlayerService.LocalPlayer
85
86local Keys = {
87 ["Unknown"] = "Unknown",
88 ["Backspace"] = "Back",
89 ["Tab"] = "Tab",
90 ["Clear"] = "Clear",
91 ["Return"] = "Return",
92 ["Pause"] = "Pause",
93 ["Escape"] = "Escape",
94 ["Space"] = "Space",
95 ["QuotedDouble"] = '"',
96 ["Hash"] = "#",
97 ["Dollar"] = "$",
98 ["Percent"] = "%",
99 ["Ampersand"] = "&",
100 ["Quote"] = "'",
101 ["LeftParenthesis"] = "(",
102 ["RightParenthesis"] = " )",
103 ["Asterisk"] = "*",
104 ["Plus"] = "+",
105 ["Comma"] = ",",
106 ["Minus"] = "-",
107 ["Period"] = ".",
108 ["Slash"] = "`",
109 ["Three"] = "3",
110 ["Seven"] = "7",
111 ["Eight"] = "8",
112 ["Colon"] = ":",
113 ["Semicolon"] = ";",
114 ["LessThan"] = "<",
115 ["GreaterThan"] = ">",
116 ["Question"] = "?",
117 ["Equals"] = "=",
118 ["At"] = "@",
119 ["LeftBracket"] = "LeftBracket",
120 ["RightBracket"] = "RightBracked",
121 ["BackSlash"] = "BackSlash",
122 ["Caret"] = "^",
123 ["Underscore"] = "_",
124 ["Backquote"] = "`",
125 ["LeftCurly"] = "{",
126 ["Pipe"] = "|",
127 ["RightCurly"] = "}",
128 ["Tilde"] = "~",
129 ["Delete"] = "Delete",
130 ["End"] = "End",
131 ["KeypadZero"] = "Keypad0",
132 ["KeypadOne"] = "Keypad1",
133 ["KeypadTwo"] = "Keypad2",
134 ["KeypadThree"] = "Keypad3",
135 ["KeypadFour"] = "Keypad4",
136 ["KeypadFive"] = "Keypad5",
137 ["KeypadSix"] = "Keypad6",
138 ["KeypadSeven"] = "Keypad7",
139 ["KeypadEight"] = "Keypad8",
140 ["KeypadNine"] = "Keypad9",
141 ["KeypadPeriod"] = "KeypadP",
142 ["KeypadDivide"] = "KeypadD",
143 ["KeypadMultiply"] = "KeypadM",
144 ["KeypadMinus"] = "KeypadM",
145 ["KeypadPlus"] = "KeypadP",
146 ["KeypadEnter"] = "KeypadE",
147 ["KeypadEquals"] = "KeypadE",
148 ["Insert"] = "Insert",
149 ["Home"] = "Home",
150 ["PageUp"] = "PageUp",
151 ["PageDown"] = "PageDown",
152 ["RightShift"] = "RShift",
153 ["LeftShift"] = "LShift",
154 ["RightControl"] = "RCtrl",
155 ["LeftControl"] = "LCtrl",
156 ["LeftAlt"] = "LAlt",
157 ["RightAlt"] = "RAlt",
158 ["MouseButton1"] = "MB1",
159 ["MouseButton2"] = "MB2",
160 ["MouseButton3"] = "MB3"
161}
162
163local function Add(class: string, propertyTable: { [string]: any }?): Instance
164 local _Instance = Instance.new(class)
165
166 if propertyTable then
167 for Property, Value in propertyTable do
168 local Success, Error = pcall(function()
169 _Instance[Property] = Value
170 end)
171
172 if not Success then
173 local Line = debug.info(2, "l")
174 warn(`error on line {Line}: {Error}`)
175 end
176 end
177 end
178
179 return _Instance
180end
181
182local function Overwrite(to_overwrite, overwrite_with)
183 for i, v in pairs(overwrite_with) do
184 if v ~= to_overwrite[i] then
185
186 if type(v) == "table" and type(to_overwrite[i]) == "table" then
187 Overwrite(to_overwrite[i], v)
188 elseif type(v) == "table" then
189 to_overwrite[i] = Overwrite({}, v)
190 else
191 to_overwrite[i] = v
192 end
193 end
194 end
195
196 return to_overwrite
197end
198
199local Lucide = {
200 activity = 10709752035,
201 aperture = 10709761813,
202 bell = 10709775704,
203 box = 10709782497,
204 circle = 10709798174,
205 cloud = 10709806740,
206 cog = 10709810948,
207 cpu = 10709813383,
208 crosshair = 10709818534,
209 eye = 10723346959,
210 file = 10723374641,
211 flame = 10723376114,
212 folder = 10723387563,
213 gamepad = 10723395457,
214 grid = 10723404936,
215 hash = 10723405975,
216 heart = 10723406885,
217 ["help-circle"] = 10723406988,
218 home = 10723407389,
219 info = 10723415903,
220 key = 10723416652,
221 layers = 10723424505,
222 list = 10723433811,
223 lock = 10723434711,
224 menu = 10734887784,
225 ["message-square"] = 10734888228,
226 moon = 10734897102,
227 ["mouse-pointer"] = 10734898476,
228 move = 10734900011,
229 palette = 10734910430,
230 save = 10734941499,
231 scan = 10734942565,
232 search = 10734943674,
233 settings = 10734950309,
234 shield = 10734951847,
235 sliders = 10734963400,
236 star = 10734966248,
237 sun = 10734974297,
238 sword = 10734975486,
239 swords = 10734975692,
240 target = 10734977012,
241 terminal = 10734982144,
242 zap = 10734975486,
243 sparkles = 10734966248,
244 user = 10747373176,
245 users = 10747373426,
246 wifi = 10747382504,
247 wrench = 10747383470,
248}
249
250local function ResolveIcon(Icon: number | string?): string
251 if Icon == nil then
252 return "rbxassetid://" .. tostring(Lucide.hash)
253 end
254 if type(Icon) == "number" then
255 return "rbxassetid://" .. tostring(Icon)
256 end
257 local AsString = tostring(Icon)
258 if AsString:match("^rbxasset") then
259 return AsString
260 end
261
262 local Name = AsString:lower():gsub("^lucide:", "")
263 local Id = Lucide[Name] or tonumber(AsString)
264 if Id then
265 return "rbxassetid://" .. tostring(Id)
266 end
267 return "rbxassetid://" .. tostring(Lucide.hash)
268end
269
270local function ClampToScreen(Object: GuiObject, Position: UDim2): UDim2
271 local Camera = workspace.CurrentCamera
272 local Viewport = Camera and Camera.ViewportSize or V2(1920, 1080)
273 local GuiService = Services:GetService("GuiService")
274 local Inset = GuiService:GetGuiInset()
275 local Size = Object.AbsoluteSize
276 if Size.X <= 0 or Size.Y <= 0 then
277 if Size.X <= 0 then Size = V2(280, 200) end
278 end
279
280 local IgnoresInset = false
281 local Node = Object
282 while Node do
283 if Node:IsA("ScreenGui") then
284 IgnoresInset = Node.IgnoreGuiInset == true
285 break
286 end
287 Node = Node.Parent
288 end
289
290 local Pad = 6
291 local UsableW = Viewport.X
292 local UsableH = Viewport.Y
293 local MinX = Pad
294 local MinY = Pad
295 if IgnoresInset then
296
297 MinY = Inset.Y + Pad
298 UsableH = Viewport.Y
299 else
300
301 UsableH = Viewport.Y - Inset.Y
302 end
303
304 local MaxX = math.max(MinX, UsableW - Size.X - Pad)
305 local MaxY = math.max(MinY, UsableH - Size.Y - Pad)
306
307 local X = MC(Position.X.Offset, MinX, MaxX)
308 local Y = MC(Position.Y.Offset, MinY, MaxY)
309
310 return UD2(Position.X.Scale, X, Position.Y.Scale, Y)
311end
312
313local function BindDrag(Object: GuiObject, Handle: GuiObject?, ClampScreen: boolean?, IgnoreUnder: GuiObject?)
314 Handle = Handle or Object
315 ClampScreen = ClampScreen == true
316
317 local Dragging = false
318 local DragStart: Vector3
319 local StartPosition: UDim2
320 local CurrentDelta = V2(0, 0)
321 local RenderConn: RBXScriptConnection?
322
323 local function ApplyPosition(Position: UDim2)
324 if ClampScreen then
325 Position = ClampToScreen(Object, Position)
326 end
327 Object.Position = Position
328 end
329
330 local function StopDrag()
331 Dragging = false
332 if RenderConn then
333 RenderConn:Disconnect()
334 RenderConn = nil
335 end
336 end
337
338 local function IsIgnored(Input: InputObject): boolean
339 if not IgnoreUnder then
340 return false
341 end
342 local Pos = Input.Position
343 local Objects = Client.PlayerGui:GetGuiObjectsAtPosition(Pos.X, Pos.Y)
344
345 local Abs = IgnoreUnder.AbsolutePosition
346 local Size = IgnoreUnder.AbsoluteSize
347 if Pos.X >= Abs.X and Pos.X <= Abs.X + Size.X and Pos.Y >= Abs.Y and Pos.Y <= Abs.Y + Size.Y then
348 return true
349 end
350 for _, Gui in Objects do
351 if Gui == IgnoreUnder or Gui:IsDescendantOf(IgnoreUnder) then
352 return true
353 end
354 end
355 return false
356 end
357
358 Handle.InputBegan:Connect(function(Input)
359 if Input.UserInputType ~= UIT.MouseButton1 and Input.UserInputType ~= UIT.Touch then
360 return
361 end
362 if IsIgnored(Input) then
363 return
364 end
365
366 Dragging = true
367 DragStart = Input.Position
368 StartPosition = Object.Position
369 CurrentDelta = V2(0, 0)
370
371 if ClampScreen and Library.OpenPopup and Library.OpenPopup.Close then
372 Library.OpenPopup.Close()
373 end
374
375 local Connection
376 Connection = Input.Changed:Connect(function()
377 if Input.UserInputState == Enum.UserInputState.End then
378 StopDrag()
379 Connection:Disconnect()
380 end
381 end)
382
383 if RenderConn then
384 RenderConn:Disconnect()
385 end
386
387 RenderConn = RunService.RenderStepped:Connect(function()
388 if not Dragging then
389 return
390 end
391
392 local Target = UD2(
393 StartPosition.X.Scale,
394 StartPosition.X.Offset + CurrentDelta.X,
395 StartPosition.Y.Scale,
396 StartPosition.Y.Offset + CurrentDelta.Y
397 )
398 if ClampScreen then
399 Target = ClampToScreen(Object, Target)
400 end
401 Object.Position = Object.Position:Lerp(Target, 0.88)
402 end)
403 end)
404
405 UserInputService.InputChanged:Connect(function(Input)
406 if not Dragging or (Input.UserInputType ~= UIT.MouseMovement and Input.UserInputType ~= UIT.Touch) then
407 return
408 end
409
410 CurrentDelta = V2(Input.Position.X - DragStart.X, Input.Position.Y - DragStart.Y)
411 end)
412
413 UserInputService.InputEnded:Connect(function(Input)
414 if Input.UserInputType == UIT.MouseButton1 or Input.UserInputType == UIT.Touch then
415 if Dragging then
416
417 ApplyPosition(UD2(
418 StartPosition.X.Scale,
419 StartPosition.X.Offset + CurrentDelta.X,
420 StartPosition.Y.Scale,
421 StartPosition.Y.Offset + CurrentDelta.Y
422 ))
423 StopDrag()
424 end
425 end
426 end)
427end
428
429local function BindSlider(Object: GuiObject, Callback: (Alpha: Vector2) -> ())
430 local Sliding = false
431
432 local function Update(Input: InputObject)
433 local Origin = Object.AbsolutePosition
434 local Size = Object.AbsoluteSize
435
436 Callback(V2(
437 Size.X > 0 and MC((Input.Position.X - Origin.X) / Size.X, 0, 1) or 0,
438 Size.Y > 0 and MC((Input.Position.Y - Origin.Y) / Size.Y, 0, 1) or 0
439 ))
440 end
441
442 Object.InputBegan:Connect(function(Input)
443 if Input.UserInputType ~= UIT.MouseButton1 and Input.UserInputType ~= UIT.Touch then
444 return
445 end
446
447 Sliding = true
448 Update(Input)
449
450 local Connection
451 Connection = Input.Changed:Connect(function()
452 if Input.UserInputState == Enum.UserInputState.End then
453 Sliding = false
454 Connection:Disconnect()
455 end
456 end)
457 end)
458
459 UserInputService.InputChanged:Connect(function(Input)
460 if not Sliding or (Input.UserInputType ~= UIT.MouseMovement and Input.UserInputType ~= UIT.Touch) then
461 return
462 end
463
464 Update(Input)
465 end)
466end
467
468local function Tween(Object: Instance, propertyTable: {}, Duration: number?, Style: Enum.EasingStyle?, Direction: Enum.EasingDirection?)
469 local Tween = TweenService:Create(Object, TI(Duration or 0.2, Style or ES.Quad, Direction or ED.Out), propertyTable)
470 Tween:Play()
471
472 return Tween
473end
474
475local function ClaimPopup(Element: {})
476 if Library.OpenPopup and Library.OpenPopup ~= Element then
477 Library.OpenPopup.Close()
478 end
479
480 Library.OpenPopup = Element
481end
482
483local function ReleasePopup(Element: {})
484 if Library.OpenPopup == Element then
485 Library.OpenPopup = nil
486 end
487end
488
489UserInputService.InputBegan:Connect(function(Input, GameProcessed)
490 if not Library.OpenPopup then
491 return
492 end
493 if Input.UserInputType ~= UIT.MouseButton1 and Input.UserInputType ~= UIT.Touch then
494 return
495 end
496
497 local Popup = Library.OpenPopup
498 local Pos = Input.Position
499
500 local function Inside(Gui: GuiObject?): boolean
501 if not Gui or not Gui.Visible then
502 return false
503 end
504 local A = Gui.AbsolutePosition
505 local S = Gui.AbsoluteSize
506 return Pos.X >= A.X and Pos.X <= A.X + S.X and Pos.Y >= A.Y and Pos.Y <= A.Y + S.Y
507 end
508
509 local Root = Popup.Frame or Popup._Frame
510 if not Root then
511 for _, Name in { "ColorpickerFrame", "Popup", "Options" } do
512 local Child = Library._Instance:FindFirstChild(Name)
513 if Child and Child.Visible then
514 Root = Child
515 break
516 end
517 end
518 end
519
520 if Root and Inside(Root) then
521 return
522 end
523
524 if Popup.Button and Inside(Popup.Button) then
525 return
526 end
527 if Popup.Settings and Inside(Popup.Settings) then
528 return
529 end
530
531 if Popup.Close then
532 Popup.Close()
533 elseif Popup.Toggle then
534 Popup.Toggle(false)
535 elseif Popup.Open then
536 Popup.Open(false)
537 end
538end)
539
540local SectionDrag = {
541 Active = false,
542 Section = nil :: any,
543 Ghost = nil :: Frame?,
544 Placeholder = nil :: Frame?,
545 SourceParent = nil :: Frame?,
546 SourceOrder = 0,
547 TargetParent = nil :: Frame?,
548 TargetIndex = 0,
549 Offset = V2(0, 0),
550 DragHeight = 60,
551 DragWidth = 200,
552 RenderConn = nil :: RBXScriptConnection?,
553}
554
555local function ClearSectionDragVisuals()
556 if SectionDrag.Ghost then
557 SectionDrag.Ghost:Destroy()
558 SectionDrag.Ghost = nil
559 end
560 if SectionDrag.Placeholder then
561 SectionDrag.Placeholder:Destroy()
562 SectionDrag.Placeholder = nil
563 end
564end
565
566local function ListColumnSections(Column: Frame, Exclude: Frame?): { Frame }
567 local List = {}
568 for _, Child in Column:GetChildren() do
569 if Child:IsA("Frame") and Child.Name == "Section" and Child ~= Exclude then
570 TIS(List, Child)
571 end
572 end
573 table.sort(List, function(a, b)
574 return a.LayoutOrder < b.LayoutOrder
575 end)
576 return List
577end
578
579local function RelayoutColumn(Column: Frame, Placeholder: Frame?, InsertIndex: number, Exclude: Frame?)
580 local Sections = ListColumnSections(Column, Exclude)
581
582 InsertIndex = MC(InsertIndex, 0, #Sections)
583
584 if Placeholder then
585 Placeholder.Parent = Column
586 Placeholder.LayoutOrder = InsertIndex * 2
587 Placeholder.Visible = true
588 end
589
590 for Index, SectionFrame in Sections do
591
592 local Slot = Index - 1
593 if Slot >= InsertIndex then
594 Slot = Slot + 1
595 end
596 SectionFrame.LayoutOrder = Slot * 2
597 end
598end
599
600local function NormalizeColumnOrders(Column: Frame)
601 local Sections = ListColumnSections(Column, nil)
602 for Index, SectionFrame in Sections do
603 SectionFrame.LayoutOrder = Index - 1
604 end
605end
606
607local function StopSectionDrag(Commit: boolean)
608 if not SectionDrag.Active then
609 return
610 end
611
612 SectionDrag.Active = false
613
614 if SectionDrag.RenderConn then
615 SectionDrag.RenderConn:Disconnect()
616 SectionDrag.RenderConn = nil
617 end
618
619 local Section = SectionDrag.Section
620 if not Section then
621 ClearSectionDragVisuals()
622 return
623 end
624
625 local Frame = Section.Frame
626 local TargetColumn = SectionDrag.TargetParent or SectionDrag.SourceParent
627 local InsertIndex = SectionDrag.TargetIndex or 0
628
629 ClearSectionDragVisuals()
630
631 if Commit and TargetColumn then
632
633 local Sections = ListColumnSections(TargetColumn, Frame)
634 InsertIndex = MC(InsertIndex, 0, #Sections)
635
636 Frame.Parent = TargetColumn
637 Frame.Visible = true
638 Frame.BackgroundTransparency = 0
639 Section.Side = TargetColumn.Name
640
641 local Order = 0
642 for Index, Sibling in Sections do
643 if Index - 1 == InsertIndex then
644 Frame.LayoutOrder = Order
645 Order = Order + 1
646 end
647 Sibling.LayoutOrder = Order
648 Order = Order + 1
649 end
650 if InsertIndex >= #Sections then
651 Frame.LayoutOrder = Order
652 end
653
654 if SectionDrag.SourceParent and SectionDrag.SourceParent ~= TargetColumn then
655 NormalizeColumnOrders(SectionDrag.SourceParent)
656 end
657 NormalizeColumnOrders(TargetColumn)
658 if SectionDrag.SourceParent and SectionDrag.SourceParent ~= TargetColumn then
659 NormalizeColumnOrders(SectionDrag.SourceParent)
660 end
661 pcall(function() Library.SaveLayout() end)
662
663 else
664 Frame.Parent = SectionDrag.SourceParent
665 Frame.LayoutOrder = SectionDrag.SourceOrder
666 Frame.Visible = true
667 Frame.BackgroundTransparency = 0
668 if SectionDrag.SourceParent then
669 NormalizeColumnOrders(SectionDrag.SourceParent)
670 end
671 end
672
673 SectionDrag.Section = nil
674 SectionDrag.SourceParent = nil
675 SectionDrag.TargetParent = nil
676end
677
678local function GetColumnAtPosition(PageFrame: Frame, ScreenPos: Vector2): Frame?
679 local Left = PageFrame:FindFirstChild("Left")
680 local Right = PageFrame:FindFirstChild("Right")
681 if not Left or not Right then
682 return nil
683 end
684
685 local MidX = (Left.AbsolutePosition.X + Left.AbsoluteSize.X + Right.AbsolutePosition.X) * 0.5
686 if ScreenPos.X < MidX then
687 return Left :: Frame
688 end
689 return Right :: Frame
690end
691
692local function ComputeInsertIndex(Column: Frame, ScreenY: number, Exclude: Frame?): number
693 local Candidates = ListColumnSections(Column, Exclude)
694
695 for Index, Child in Candidates do
696 local Mid = Child.AbsolutePosition.Y + Child.AbsoluteSize.Y * 0.5
697 if ScreenY < Mid then
698 return Index - 1
699 end
700 end
701
702 return #Candidates
703end
704
705local function EnsurePlaceholder(Height: number): Frame
706 if SectionDrag.Placeholder then
707 return SectionDrag.Placeholder
708 end
709
710 local Placeholder = Add("Frame", {
711 Name = "SectionPlaceholder";
712 BackgroundColor3 = RGB(78, 88, 129);
713 BackgroundTransparency = 0.65;
714 BorderSizePixel = 0;
715 Size = UD2(1, 0, 0, Height);
716 ZIndex = 5;
717 }) :: Frame
718 Add("UICorner", { Parent = Placeholder; CornerRadius = UD(0, 5); })
719 Add("UIStroke", {
720 Parent = Placeholder;
721 ApplyStrokeMode = ASM.Border;
722 Color = RGB(138, 156, 229);
723 Thickness = 1.5;
724 Transparency = 0.2;
725 })
726
727 SectionDrag.Placeholder = Placeholder
728 return Placeholder
729end
730
731local function UpdateSectionDrag(MousePos: Vector2)
732 if not SectionDrag.Active or not SectionDrag.Section then
733 return
734 end
735
736 local Section = SectionDrag.Section
737 local Frame = Section.Frame
738 local PageFrame = Section.PageFrame
739 if not PageFrame then
740 return
741 end
742
743 if SectionDrag.Ghost then
744 local Target = UFO(MousePos.X - SectionDrag.Offset.X, MousePos.Y - SectionDrag.Offset.Y)
745 SectionDrag.Ghost.Position = SectionDrag.Ghost.Position:Lerp(Target, 0.45)
746 end
747
748 local Column = GetColumnAtPosition(PageFrame, MousePos)
749 if not Column then
750 return
751 end
752
753 local InsertIndex = ComputeInsertIndex(Column, MousePos.Y, Frame)
754 SectionDrag.TargetParent = Column
755 SectionDrag.TargetIndex = InsertIndex
756
757 local Placeholder = EnsurePlaceholder(SectionDrag.DragHeight)
758 Placeholder.Size = UD2(1, 0, 0, SectionDrag.DragHeight)
759
760 RelayoutColumn(Column, Placeholder, InsertIndex, Frame)
761
762 local PageLeft = PageFrame:FindFirstChild("Left")
763 local PageRight = PageFrame:FindFirstChild("Right")
764 local Other = if Column == PageLeft then PageRight else PageLeft
765 if Other and Other ~= Column then
766
767 if SectionDrag.Placeholder and SectionDrag.Placeholder.Parent == Other then
768 SectionDrag.Placeholder.Parent = Column
769 end
770 RelayoutColumn(Other :: Frame, nil, 0, Frame)
771 end
772end
773
774local function BeginSectionDrag(Section: any, Input: InputObject)
775 if SectionDrag.Active then
776 return
777 end
778
779 local Frame = Section.Frame
780 if not Frame:FindFirstChild("Header") then
781 return
782 end
783
784 SectionDrag.Active = true
785 SectionDrag.Section = Section
786 SectionDrag.SourceParent = Frame.Parent :: Frame
787 SectionDrag.SourceOrder = Frame.LayoutOrder
788 SectionDrag.TargetParent = SectionDrag.SourceParent
789 SectionDrag.TargetIndex = Frame.LayoutOrder
790 SectionDrag.DragHeight = math.max(Frame.AbsoluteSize.Y, 60)
791 SectionDrag.DragWidth = Frame.AbsoluteSize.X
792 SectionDrag.Offset = V2(
793 Input.Position.X - Frame.AbsolutePosition.X,
794 Input.Position.Y - Frame.AbsolutePosition.Y
795 )
796
797 Frame.Visible = false
798 Frame.Parent = Library._Instance
799
800 local Ghost = Frame:Clone()
801 Ghost.Name = "SectionGhost"
802 Ghost.Parent = Library._Instance
803 Ghost.Visible = true
804 Ghost.BackgroundTransparency = 0.2
805 Ghost.Size = UFO(SectionDrag.DragWidth, SectionDrag.DragHeight)
806 Ghost.Position = UFO(
807 Input.Position.X - SectionDrag.Offset.X,
808 Input.Position.Y - SectionDrag.Offset.Y
809 )
810 Ghost.ZIndex = PopupZ + 5
811 Ghost.AutomaticSize = AS.None
812
813 for _, Desc in Ghost:GetDescendants() do
814 if Desc:IsA("GuiObject") then
815 if Desc:IsA("TextLabel") or Desc:IsA("TextButton") or Desc:IsA("TextBox") then
816 Desc.TextTransparency = math.min(Desc.TextTransparency + 0.3, 0.8)
817 elseif Desc:IsA("ImageLabel") or Desc:IsA("ImageButton") then
818 Desc.ImageTransparency = math.min(Desc.ImageTransparency + 0.3, 0.8)
819 elseif Desc:IsA("Frame") and Desc.BackgroundTransparency < 1 then
820 Desc.BackgroundTransparency = math.min(Desc.BackgroundTransparency + 0.15, 0.85)
821 end
822 end
823 end
824
825 SectionDrag.Ghost = Ghost
826
827 local Placeholder = EnsurePlaceholder(SectionDrag.DragHeight)
828 local SourceSections = ListColumnSections(SectionDrag.SourceParent, Frame)
829 local StartIndex = 0
830 for Index, Sibling in SourceSections do
831 if Sibling.LayoutOrder >= SectionDrag.SourceOrder then
832 StartIndex = Index - 1
833 break
834 end
835 StartIndex = Index
836 end
837 SectionDrag.TargetIndex = StartIndex
838 RelayoutColumn(SectionDrag.SourceParent, Placeholder, StartIndex, Frame)
839
840 if SectionDrag.RenderConn then
841 SectionDrag.RenderConn:Disconnect()
842 end
843
844 SectionDrag.RenderConn = RunService.RenderStepped:Connect(function()
845 if not SectionDrag.Active then
846 return
847 end
848 local Mouse = UserInputService:GetMouseLocation()
849 local GuiService = Services:GetService("GuiService")
850 local Inset = GuiService:GetGuiInset()
851 UpdateSectionDrag(V2(Mouse.X, Mouse.Y - Inset.Y))
852 end)
853
854 UpdateSectionDrag(V2(Input.Position.X, Input.Position.Y))
855end
856
857UserInputService.InputEnded:Connect(function(Input)
858 if Input.UserInputType ~= UIT.MouseButton1 and Input.UserInputType ~= UIT.Touch then
859 return
860 end
861 if SectionDrag.Active then
862 StopSectionDrag(true)
863 end
864end)
865
866local function SectionBuilder(Container: Frame)
867 return function(self: Library, propertyTable: {})
868 local Section = Overwrite({
869 Name = "",
870 Icon = "hash",
871 Side = "Left",
872 }, propertyTable or {})
873 setmetatable(Section, { __index = Library.Elements })
874
875 local Column = Container[Section.Side]
876 local NextOrder = 0
877 for _, Child in Column:GetChildren() do
878 if Child:IsA("Frame") and Child.Name == "Section" then
879 NextOrder = math.max(NextOrder, Child.LayoutOrder + 1)
880 end
881 end
882
883 local SectionFrame = Add("Frame", {
884 Parent = Column;
885 Name = "Section";
886 AutomaticSize = AS.Y;
887 BackgroundColor3 = RGB(15, 14, 15);
888 BorderColor3 = RGB(0, 0, 0);
889 BorderSizePixel = 0;
890 Size = UFS(1, 0);
891 LayoutOrder = NextOrder;
892 }) :: Frame
893 local Header = Add("Frame", {
894 Parent = SectionFrame;
895 Name = "Header";
896 BackgroundColor3 = RGB(20, 20, 21);
897 BorderColor3 = RGB(0, 0, 0);
898 BorderSizePixel = 0;
899 Size = UD2(1, 0, 0, 35);
900 }) :: Frame
901 local Elements = Add("Frame", {
902 Parent = SectionFrame;
903 Name = "Elements";
904 AutomaticSize = AS.Y;
905 BackgroundColor3 = RGB(255, 255, 255);
906 BackgroundTransparency = 1;
907 BorderColor3 = RGB(0, 0, 0);
908 BorderSizePixel = 0;
909 Position = UFO(0, 35);
910 Size = UFS(1, 0);
911 }) :: Frame
912 Add("UICorner", { Parent = SectionFrame; CornerRadius = UD(0, 5); })
913 Add("UICorner", { Parent = Header; BottomLeftRadius = UD(0, 0); BottomRightRadius = UD(0, 0); TopLeftRadius = UD(0, 5); TopRightRadius = UD(0, 5); })
914 Add("ImageLabel", {
915 Parent = Header;
916 Name = "Icon";
917 BackgroundColor3 = RGB(255, 255, 255);
918 BackgroundTransparency = 1;
919 BorderColor3 = RGB(0, 0, 0);
920 BorderSizePixel = 0;
921 Image = ResolveIcon(Section.Icon);
922 Position = UFS(0, 0.5);
923 Size = UFO(16, 16);
924 })
925 Add("UIListLayout", {
926 Parent = Header;
927 FillDirection = FD.Horizontal;
928 Padding = UD(0, 5);
929 SortOrder = SO.LayoutOrder;
930 VerticalAlignment = VFA.Center;
931 })
932 Add("UIPadding", { Parent = Header; PaddingLeft = UD(0, 10); })
933 Add("TextLabel", {
934 Parent = Header;
935 Name = "Title";
936 AutomaticSize = AS.XY;
937 BackgroundColor3 = RGB(255, 255, 255);
938 BackgroundTransparency = 1;
939 BorderColor3 = RGB(0, 0, 0);
940 BorderSizePixel = 0;
941 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
942 LayoutOrder = 1;
943 Text = Section.Name;
944 TextColor3 = RGB(255, 255, 255);
945 TextSize = 14;
946 })
947 local SectionStroke = Add("UIStroke", { Parent = SectionFrame; ApplyStrokeMode = ASM.Border; Color = Library.Theme.SectionBorder; Thickness = 1; })
948 Library.ThemeLink(SectionFrame, "BackgroundColor3", "Surface")
949 Library.ThemeLink(SectionStroke, "Color", "SectionBorder")
950 Add("UIPadding", {
951 Parent = Elements;
952 PaddingBottom = UD(0, 10);
953 PaddingLeft = UD(0, 10);
954 PaddingRight = UD(0, 10);
955 PaddingTop = UD(0, 10);
956 })
957 Add("UIListLayout", { Parent = Elements; Padding = UD(0, 10); SortOrder = SO.LayoutOrder; })
958
959 Section.Content = Elements
960 Section.Frame = SectionFrame
961 Section.PageFrame = Container
962 Section.Side = Section.Side
963
964 local DragThreshold = 6
965
966 Header.InputBegan:Connect(function(Input)
967 if Input.UserInputType ~= UIT.MouseButton1 and Input.UserInputType ~= UIT.Touch then
968 return
969 end
970 if SectionDrag.Active then
971 return
972 end
973
974 local PressPos = Input.Position
975 local MoveConn: RBXScriptConnection?
976 local EndConn: RBXScriptConnection?
977
978 local function Cleanup()
979 if MoveConn then
980 MoveConn:Disconnect()
981 MoveConn = nil
982 end
983 if EndConn then
984 EndConn:Disconnect()
985 EndConn = nil
986 end
987 end
988
989 MoveConn = UserInputService.InputChanged:Connect(function(MoveInput)
990 if MoveInput.UserInputType ~= UIT.MouseMovement and MoveInput.UserInputType ~= UIT.Touch then
991 return
992 end
993 if SectionDrag.Active then
994 Cleanup()
995 return
996 end
997
998 local Delta = (MoveInput.Position - PressPos).Magnitude
999 if Delta >= DragThreshold then
1000 Cleanup()
1001 BeginSectionDrag(Section, MoveInput)
1002 end
1003 end)
1004
1005 EndConn = Input.Changed:Connect(function()
1006 if Input.UserInputState == Enum.UserInputState.End then
1007 Cleanup()
1008 end
1009 end)
1010 end)
1011
1012 TIS(Library.Sections, Section)
1013 return Section
1014 end
1015end
1016
1017local function PageContent(Entry: {}, Container: Frame, Registry: {}, OnOpen: (() -> ())?, OnClose: (() -> ())?)
1018 local ContentFrame = Add("Frame", { Parent = Container; Name = "PageFrame"; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UD2(0, 0, 0, 12); Size = UFS(1, 1); Visible = false; }) :: Frame
1019
1020 local function MakeColumn(Name: string, Props: {}): ScrollingFrame
1021 local Column = Add("ScrollingFrame", {
1022 Parent = ContentFrame;
1023 Name = Name;
1024 BackgroundColor3 = RGB(255, 255, 255);
1025 BackgroundTransparency = 1;
1026 BorderColor3 = RGB(0, 0, 0);
1027 BorderSizePixel = 0;
1028 ScrollBarThickness = 0;
1029 ScrollBarImageColor3 = RGB(78, 88, 129);
1030 ScrollBarImageTransparency = 1;
1031 ScrollingDirection = SBD.Y;
1032 CanvasSize = UD2(0, 0, 0, 0);
1033 AutomaticCanvasSize = AS.Y;
1034 ElasticBehavior = Enum.ElasticBehavior.Never;
1035 ClipsDescendants = true;
1036 }) :: ScrollingFrame
1037
1038 for Key, Value in Props do
1039 Column[Key] = Value
1040 end
1041
1042 Add("UIListLayout", { Parent = Column; Padding = UD(0, 12); SortOrder = SO.LayoutOrder; })
1043
1044 Add("UIPadding", {
1045 Parent = Column;
1046 PaddingLeft = UD(0, 2);
1047 PaddingRight = UD(0, 6);
1048 PaddingTop = UD(0, 2);
1049 PaddingBottom = UD(0, 8);
1050 })
1051
1052 return Column
1053 end
1054
1055 local Left = MakeColumn("Left", {
1056 Size = UD2(0.5, -6, 1, 0);
1057 })
1058 local Right = MakeColumn("Right", {
1059 AnchorPoint = V2(1, 0);
1060 Position = UFS(1, 0);
1061 Size = UD2(0.5, -6, 1, 0);
1062 })
1063
1064 Entry.Frame = ContentFrame
1065 Entry.Section = SectionBuilder(ContentFrame)
1066 Library.PageFrames = Library.PageFrames or {}
1067 Library.PageFrames[ContentFrame] = Entry
1068
1069 Entry.IsOpen = false
1070
1071 Entry.Open = function()
1072
1073 if Entry.IsOpen then
1074 return
1075 end
1076
1077 Entry.IsOpen = true
1078
1079 for _, Other in Registry do
1080 if Other ~= Entry and Other.IsOpen then
1081 Other.Close()
1082 end
1083 end
1084
1085 ContentFrame.Position = UD2(0, 0, 0, 12)
1086 ContentFrame.Visible = true
1087 Tween(ContentFrame, { Position = UD2(0, 0, 0, 0) }, 0.3, ES.Quint)
1088
1089 if OnOpen then
1090 OnOpen()
1091 end
1092 end
1093
1094 Entry.Close = function()
1095 Entry.IsOpen = false
1096 ContentFrame.Visible = false
1097
1098 if OnClose then
1099 OnClose()
1100 end
1101 end
1102
1103 TIS(Registry, Entry)
1104 return Entry
1105end
1106
1107Library.Elements.Label = function(self: Library, propertyTable: {})
1108 local Label = Overwrite({
1109 Text = "",
1110 }, propertyTable or {})
1111 setmetatable(Label, { __index = Library.SubElements })
1112
1113 local LabelFrame = Add("Frame", { Parent = self.Content; Name = "LabelFrame";BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(1, 0, 0, 14); }) :: Frame
1114 local LeftContent = Add("Frame", { Parent = LabelFrame; Name = "LeftContent"; AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; }) :: Frame
1115 local RightContent = Add("Frame", { Parent = LabelFrame; Name = "RightContent"; AnchorPoint = V2(1, 0); AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFS(1, 0); }) :: Frame
1116 Add("TextLabel", { LayoutOrder = 99; Parent = LeftContent; Name = "Label"; AnchorPoint = V2(0, 0.5); AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Position = UD2(0, 38, 0.5, 0); Size = UFO(0, 9); Text = Label.Text; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.2; })
1117 Add("UIListLayout", { Parent = LeftContent; FillDirection = FD.Horizontal; Padding = UD(0, 10); SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
1118 Add("UIListLayout", { Parent = RightContent; FillDirection = FD.Horizontal; HorizontalAlignment = HFA.Right; Padding = UD(0, 5); SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
1119
1120 Label.RightContent = RightContent
1121 Label.LeftContent = LeftContent
1122
1123 TIS(Library.Searchable, { Frame = LabelFrame; Text = Label.Text; Section = self })
1124 return Label
1125end
1126
1127Library.Elements.Slider = function(self: Library, propertyTable: {})
1128 local Slider = Overwrite({
1129 Name = "FOV Radius",
1130 Suffix = "°",
1131 Value = 1,
1132 Increment = 0.1,
1133 Max = 1,
1134 Min = 0,
1135 Callback = function() end
1136 }, propertyTable or {})
1137
1138 local Decimals = MM(#(tostring(Slider.Increment):match("%.(%d+)") or ""), 4)
1139
1140 local SliderFrame = Add("Frame", { Parent = self.Content; Name = "SliderFrame"; AutomaticSize = AS.Y; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UFS(1, 0); }) :: Frame
1141 local Button = Add("TextButton", { Parent = SliderFrame; Name = "Button"; AutoButtonColor = false; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxasset://fonts/families/SourceSansPro.json", FW.Regular, FS.Normal); Position = UFO(0, 18); Size = UD2(1, 0, 0, 12); Text = ""; TextColor3 = RGB(0, 0, 0); TextSize = 14; }) :: TextButton
1142 local Overlay = Add("Frame", { Parent = Button; Name = "Overlay"; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(0, 0, 1, 0); }) :: Frame
1143 local Circle = Add("Frame", { Parent = Button; Name = "Circle"; AnchorPoint = V2(1, 0.5); BackgroundColor3 = RGB(0, 0, 0); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UD2(1, -3, 0.5, 0); Size = UFO(8, 8); }) :: Frame
1144 Add("TextLabel", { Parent = SliderFrame; Name = "Title"; AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UFO(0, 9); Text = Slider.Name; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.2; })
1145 local Amount = Add("TextLabel", { Parent = SliderFrame; Name = "Amount"; AnchorPoint = V2(1, 0); AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Position = UFS(1, 0); Size = UFO(0, 9); Text = ""; TextColor3 = RGB(255, 255, 255); TextSize = 13; }) :: TextLabel
1146 Add("UICorner", { Parent = Button; CornerRadius = UD(0, 5); })
1147 local SliderGrad = Add("UIGradient", { Parent = Overlay; Color = CS{ CSK(0, Library.Theme.AccentDark), CSK(1, Library.Theme.Accent) }; Rotation = -90; })
1148 Library.ThemeLink(SliderGrad, "Gradient", "AccentDark", "Accent")
1149 Add("UICorner", { Parent = Overlay; CornerRadius = UD(0, 5); })
1150 Add("UICorner", { Parent = Circle; CornerRadius = UD(1, 0); })
1151
1152 Slider.Set = function(Value: number)
1153 Value = MC(MR(Value / Slider.Increment) * Slider.Increment, Slider.Min, Slider.Max)
1154 Slider.Value = tonumber(SF(`%.{Decimals}f`, Value))
1155
1156 local Range = Slider.Max - Slider.Min
1157 local Alpha = Range > 0 and (Slider.Value - Slider.Min) / Range or 0
1158 local Fade = MC(1 - Alpha / 0.05, 0, 1)
1159
1160 Tween(Overlay, { Size = UD2(Alpha, 0, 1, 0); BackgroundTransparency = Fade }, 0.08)
1161 Tween(Circle, { Position = UD2(Alpha, -3, 0.5, 0); BackgroundTransparency = Fade }, 0.08)
1162
1163 Amount.Text = SF(`%.{Decimals}f`, Slider.Value) .. Slider.Suffix
1164 Slider.Callback(Slider.Value)
1165 end
1166
1167 BindSlider(Button, function(Alpha)
1168 Slider.Set(Slider.Min + (Slider.Max - Slider.Min) * Alpha.X)
1169 end)
1170
1171 TIS(Library.Searchable, { Frame = SliderFrame; Text = Slider.Name; Section = self })
1172
1173 if propertyTable and propertyTable.Flag then
1174 Slider.Flag = propertyTable.Flag
1175 Library.RegisterFlag(Slider.Flag, { Value = Slider.Value; Set = Slider.Set })
1176 end
1177
1178 Slider.Set(Slider.Value)
1179 return Slider
1180end
1181
1182Library.Elements.Dropdown = function(self: Library, propertyTable: {})
1183 local Dropdown = Overwrite({
1184 Name = "",
1185 Options = {},
1186 Value = "",
1187 Multi = false,
1188 Search = false,
1189 Callback = function() end,
1190 }, propertyTable or {})
1191
1192 local OptionList = Add("TextButton", { Parent = Library._Instance; Name = "Options"; AutoButtonColor = false; AutomaticSize = AS.Y; BackgroundColor3 = RGB(15, 14, 15); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFS(0.3761225640773773, 0.42204996943473816); Size = UFO(253, 0); Text = ""; Visible = false; ZIndex = PopupZ; }) :: TextButton
1193 Add("UICorner", { Parent = OptionList; CornerRadius = UD(0, 5); })
1194 Add("UIStroke", { Parent = OptionList; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
1195 Add("UIPadding", { Parent = OptionList; })
1196 Add("UIShadow", { Parent = OptionList; BlurRadius = UD(0, 20); Spread = UFO(5, 5); Transparency = 0.65; })
1197 Add("UIListLayout", { Parent = OptionList; SortOrder = SO.LayoutOrder; })
1198
1199 local ButtonFrame = Add("Frame", { Parent = self.Content; Name = "ButtonFrame"; Active = true; AutomaticSize = AS.Y; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UFS(1, 0); }) :: Frame
1200 local InputFrame = Add("Frame", { Parent = ButtonFrame; Name = "InputFrame"; Active = true; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(0, 18); Selectable = true; Size = UD2(1, 0, 0, 22); }) :: Frame
1201 Add("TextLabel", { Parent = ButtonFrame; Name = "Title"; AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UFO(0, 9); Text = Dropdown.Name; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.2; })
1202 Add("UICorner", { Parent = InputFrame; CornerRadius = UD(0, 5); })
1203 Add("UIPadding", { Parent = InputFrame; PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); })
1204 local Icon = Add("ImageLabel", { Parent = InputFrame; Name = "Icon"; AnchorPoint = V2(1, 0.5); BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Image = "rbxassetid://95865107607162"; ImageTransparency = 0.2; Position = UFS(1, 0.5); ResampleMode = Enum.ResamplerMode.Pixelated; ScaleType = SCL.Fit; Size = UFO(14, 14); }) :: ImageLabel
1205 local InputText = Add("TextButton", { Parent = InputFrame; Name = "Input"; BackgroundColor3 = RGB(20, 20, 21); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UD2(1, -24, 1, 0); Text = ""; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.2; TextTruncate = ETT.SplitWord; TextXAlignment = TXA.Left; }) :: TextButton
1206
1207 local Buttons = {}
1208
1209 local function GetMultiValue(): { string }
1210 if type(Dropdown.Value) ~= "table" then
1211 return {}
1212 end
1213 return Dropdown.Value
1214 end
1215
1216 local function IsSelected(Option: string): boolean
1217 if Dropdown.Multi then
1218 return TF(GetMultiValue(), Option) ~= nil
1219 end
1220 return Dropdown.Value == Option
1221 end
1222
1223 local function Highlight()
1224 for _, Button in Buttons do
1225 local Selected = IsSelected(Button.Text)
1226 Tween(Button, {
1227 BackgroundTransparency = Selected and 0 or 1;
1228 TextTransparency = Selected and 0.15 or 0.45;
1229 BackgroundColor3 = Selected and RGB(28, 30, 38) or RGB(20, 20, 21);
1230 }, 0.1)
1231 end
1232 end
1233
1234 local function Choose(Option: string)
1235 if not Dropdown.Multi then
1236 Dropdown.Set(Option)
1237 Dropdown.Open(false)
1238 return
1239 end
1240
1241 local Selected = TC(GetMultiValue())
1242 local Index = TF(Selected, Option)
1243
1244 if Index then
1245 TR(Selected, Index)
1246 else
1247 TIS(Selected, Option)
1248 end
1249
1250 Dropdown.Set(Selected)
1251 end
1252
1253 local SearchBoxDrop = nil
1254 if Dropdown.Search then
1255 SearchBoxDrop = Add("TextBox", {
1256 Parent = OptionList;
1257 Name = "SearchBox";
1258 BackgroundColor3 = RGB(20, 20, 21);
1259 BorderSizePixel = 0;
1260 ClearTextOnFocus = false;
1261 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
1262 PlaceholderText = "Search…";
1263 PlaceholderColor3 = RGB(255, 255, 255);
1264 Text = "";
1265 TextColor3 = RGB(255, 255, 255);
1266 TextSize = 13;
1267 TextTransparency = 0.2;
1268 TextXAlignment = TXA.Left;
1269 Size = UD2(1, 0, 0, 26);
1270 LayoutOrder = -1;
1271 })
1272 Add("UIPadding", { Parent = SearchBoxDrop; PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); })
1273 Add("UICorner", { Parent = SearchBoxDrop; CornerRadius = UD(0, 5); })
1274 SearchBoxDrop:GetPropertyChangedSignal("Text"):Connect(function()
1275 Build()
1276 end)
1277 end
1278
1279 local function Build()
1280 for _, Button in Buttons do
1281 Button:Destroy()
1282 end
1283
1284 table.clear(Buttons)
1285
1286 local Filter = SearchBoxDrop and SearchBoxDrop.Text:lower() or ""
1287 local VisibleOptions = {}
1288 for _, Option in Dropdown.Options do
1289 if Filter == "" or tostring(Option):lower():find(Filter, 1, true) then
1290 TIS(VisibleOptions, Option)
1291 end
1292 end
1293
1294 for Index, Option in VisibleOptions do
1295 local Button = Add("TextButton", { Parent = OptionList; Name = Option; AutoButtonColor = false; BackgroundColor3 = RGB(20, 20, 21); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); LayoutOrder = Index; Size = UD2(1, 0, 0, 22); Text = Option; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.5; TextWrapped = true; TextXAlignment = TXA.Left; }) :: TextButton
1296 Add("UIPadding", { Parent = Button; PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); })
1297
1298 local First = Index == 1
1299 local Last = Index == #VisibleOptions
1300
1301 Add("UICorner", { Parent = Button;
1302 TopLeftRadius = First and UD(0, 5) or UD(0, 0);
1303 TopRightRadius = First and UD(0, 5) or UD(0, 0);
1304 BottomLeftRadius = Last and UD(0, 5) or UD(0, 0);
1305 BottomRightRadius = Last and UD(0, 5) or UD(0, 0);
1306 })
1307
1308 Button.MouseEnter:Connect(function()
1309 if not IsSelected(Option) then
1310 Tween(Button, { BackgroundTransparency = 0.35; BackgroundColor3 = Library.Theme.SurfaceAlt }, 0.08)
1311 end
1312 end)
1313 Button.MouseLeave:Connect(function()
1314 local Selected = IsSelected(Option)
1315 Tween(Button, {
1316 BackgroundTransparency = Selected and 0 or 1;
1317 BackgroundColor3 = Selected and RGB(28, 30, 38) or RGB(20, 20, 21);
1318 }, 0.08)
1319 end)
1320 Button.Activated:Connect(function()
1321 Choose(Option)
1322 end)
1323
1324 TIS(Buttons, Button)
1325 end
1326
1327 Highlight()
1328 end
1329
1330 Dropdown.Set = function(Value: string | { string })
1331 if Dropdown.Multi then
1332 if type(Value) ~= "table" then
1333 Value = Value ~= nil and Value ~= "" and { tostring(Value) } or {}
1334 end
1335 Dropdown.Value = Value
1336 InputText.Text = #Value > 0 and TCC(Value, ", ") or "None"
1337 else
1338 Dropdown.Value = Value
1339 InputText.Text = tostring(Value or "")
1340 end
1341
1342 if Dropdown.Flag then
1343 Library.Flags[Dropdown.Flag] = Library.Flags[Dropdown.Flag] or {}
1344 Library.Flags[Dropdown.Flag].Value = Dropdown.Value
1345 Library.Flags[Dropdown.Flag].Set = Dropdown.Set
1346 end
1347
1348 Highlight()
1349 Dropdown.Callback(Dropdown.Value)
1350 end
1351
1352 Dropdown.UpdateOptions = function(NewOptions: { string })
1353 Dropdown.Options = NewOptions
1354 Build()
1355
1356 if Dropdown.Multi then
1357 local Kept = {}
1358 local Current = type(Dropdown.Value) == "table" and Dropdown.Value or {}
1359 for _, Option in Current do
1360 if TF(NewOptions, Option) then
1361 TIS(Kept, Option)
1362 end
1363 end
1364
1365 Dropdown.Set(Kept)
1366 elseif not TF(NewOptions, Dropdown.Value) then
1367 Dropdown.Set(NewOptions[1] or "")
1368 end
1369 end
1370
1371 Dropdown.Frame = OptionList
1372 Dropdown.Button = ButtonFrame
1373
1374 Dropdown.Close = function()
1375 Dropdown.Open(false)
1376 end
1377
1378 Dropdown.Open = function(State: boolean?)
1379 if State == nil then
1380 State = not OptionList.Visible
1381 end
1382
1383 if State then
1384 ClaimPopup(Dropdown)
1385
1386 OptionList.Size = UFO(InputFrame.AbsoluteSize.X, 0)
1387
1388 local Target = UFO(
1389 InputFrame.AbsolutePosition.X,
1390 InputFrame.AbsolutePosition.Y + InputFrame.AbsoluteSize.Y + 4
1391 )
1392
1393 OptionList.Position = Target - UFO(0, 8)
1394 OptionList.Visible = true
1395 Tween(OptionList, { Position = Target }, 0.22, ES.Quint)
1396 else
1397 OptionList.Visible = false
1398 ReleasePopup(Dropdown)
1399 end
1400
1401 Tween(Icon, { Rotation = State and 180 or 0 }, 0.18)
1402 end
1403
1404 local LastToggle = 0
1405
1406 local function Activate()
1407 if os.clock() - LastToggle < 0.18 then
1408 return
1409 end
1410 LastToggle = os.clock()
1411
1412 Dropdown.Open(not OptionList.Visible)
1413 end
1414
1415 for _, Object in { ButtonFrame, InputFrame } do
1416 Object.InputBegan:Connect(function(Input)
1417 if Input.UserInputType ~= UIT.MouseButton1 and Input.UserInputType ~= UIT.Touch then
1418 return
1419 end
1420 Activate()
1421 end)
1422 end
1423
1424 InputText.Activated:Connect(Activate)
1425
1426 TIS(Library.Searchable, { Frame = ButtonFrame; Text = Dropdown.Name; Section = self })
1427
1428 Build()
1429
1430 if propertyTable and propertyTable.Flag then
1431 Dropdown.Flag = propertyTable.Flag
1432 Library.RegisterFlag(Dropdown.Flag, { Value = Dropdown.Value; Set = Dropdown.Set })
1433 end
1434
1435 if Dropdown.Multi then
1436
1437 Dropdown.Set(type(Dropdown.Value) == "table" and Dropdown.Value or {})
1438 else
1439 Dropdown.Set(Dropdown.Value ~= "" and Dropdown.Value or Dropdown.Options[1] or "")
1440 end
1441
1442 return Dropdown
1443end
1444
1445Library.Elements.Input = function(self: Library, propertyTable: {})
1446 local Input = Overwrite({
1447 Name = "",
1448 Value = "",
1449 Placeholder = "",
1450 Callback = function() end,
1451 }, propertyTable or {})
1452
1453 local TextBox = Add("Frame", { Parent = self.Content; Name = "TextBox"; AutomaticSize = AS.Y; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UFS(1, 0); }) :: Frame
1454 local InputFrame = Add("Frame", { Parent = TextBox; Name = "InputFrame"; Active = true; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(0, 18); Selectable = true; Size = UD2(1, 0, 0, 22); }) :: Frame
1455 Add("TextLabel", { Parent = TextBox; Name = "Title"; AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UFO(0, 9); Text = Input.Name; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.2; })
1456 local Box = Add("TextBox", { Parent = InputFrame; Name = "Input"; BackgroundColor3 = RGB(20, 20, 21); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; ClearTextOnFocus = false; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); PlaceholderColor3 = RGB(255, 255, 255); PlaceholderText = Input.Placeholder; Size = UD2(1, -24, 1, 0); Text = Input.Value; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.2; TextTruncate = ETT.SplitWord; TextXAlignment = TXA.Left; }) :: TextBox
1457 Add("ImageLabel", { Parent = InputFrame; Name = "Icon"; AnchorPoint = V2(1, 0.5); BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Image = "rbxassetid://96386750273341"; ImageTransparency = 0.2; Position = UFS(1, 0.5); ResampleMode = Enum.ResamplerMode.Pixelated; Size = UFO(14, 14); })
1458 Add("UIPadding", { Parent = InputFrame; PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); })
1459 Add("UICorner", { Parent = InputFrame; CornerRadius = UD(0, 5); })
1460
1461 Input.Set = function(Value: string)
1462 Input.Value = Value
1463 Box.Text = Value
1464
1465 Input.Callback(Value)
1466 end
1467
1468 Box.FocusLost:Connect(function()
1469 Input.Set(Box.Text)
1470 end)
1471
1472 InputFrame.InputBegan:Connect(function(InputObject)
1473 if InputObject.UserInputType ~= UIT.MouseButton1 and InputObject.UserInputType ~= UIT.Touch then
1474 return
1475 end
1476
1477 Box:CaptureFocus()
1478 end)
1479
1480 if propertyTable and propertyTable.Flag then
1481 Input.Flag = propertyTable.Flag
1482 Library.RegisterFlag(Input.Flag, { Value = Input.Value; Set = Input.Set })
1483 end
1484
1485 TIS(Library.Searchable, { Frame = TextBox; Text = Input.Name; Section = self })
1486 return Input
1487end
1488
1489Library.Elements.Button = function(self: Library, propertyTable: {})
1490 local Button = Overwrite({
1491 Name = "Button";
1492 Callback = function() end;
1493 Height = 30;
1494 Width = 1;
1495 }, propertyTable or {})
1496
1497 local Width = typeof(Button.Width) == "number" and MC(Button.Width, 0.2, 1) or 1
1498
1499 local ParentFrame = self.Content
1500 if Width < 0.999 then
1501 if not self._ButtonRow or self._ButtonRowRemain < Width - 0.001 then
1502 self._ButtonRow = Add("Frame", {
1503 Parent = self.Content;
1504 Name = "ButtonRow";
1505 BackgroundTransparency = 1;
1506 BorderSizePixel = 0;
1507 Size = UD2(1, 0, 0, Button.Height);
1508 })
1509 Add("UIListLayout", {
1510 Parent = self._ButtonRow;
1511 FillDirection = FD.Horizontal;
1512 Padding = UD(0, 8);
1513 SortOrder = SO.LayoutOrder;
1514 })
1515 self._ButtonRowRemain = 1
1516 end
1517 ParentFrame = self._ButtonRow
1518 self._ButtonRowRemain = self._ButtonRowRemain - Width
1519 if self._ButtonRowRemain <= 0.05 then
1520 self._ButtonRow = nil
1521 self._ButtonRowRemain = 0
1522 end
1523 else
1524 self._ButtonRow = nil
1525 self._ButtonRowRemain = 0
1526 end
1527
1528 local Frame = Add("Frame", {
1529 Parent = ParentFrame;
1530 Name = "ButtonFrame";
1531 BackgroundTransparency = 1;
1532 BorderSizePixel = 0;
1533 Size = UD2(Width, Width < 1 and -4 or 0, 1, 0);
1534 })
1535 if Width >= 0.999 then
1536 Frame.Size = UD2(1, 0, 0, Button.Height)
1537 end
1538
1539 local Click = Add("TextButton", {
1540 Parent = Frame;
1541 Name = "Click";
1542 AutoButtonColor = false;
1543 BackgroundColor3 = RGB(22, 22, 24);
1544 BorderSizePixel = 0;
1545 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
1546 Size = UFS(1, 1);
1547 Text = Button.Name;
1548 TextColor3 = RGB(255, 255, 255);
1549 TextSize = 13;
1550 TextTransparency = 0.12;
1551 })
1552 Add("UICorner", { Parent = Click; CornerRadius = UD(0, 6); })
1553 local BtnStroke = Add("UIStroke", { Parent = Click; ApplyStrokeMode = ASM.Border; Color = Library.Theme.Border; })
1554 Library.ThemeLink(BtnStroke, "Color", "Border")
1555 local Grad = Add("UIGradient", {
1556 Parent = Click;
1557 Color = CS{ CSK(0, Library.Theme.AccentDark), CSK(1, Library.Theme.Accent) };
1558 Rotation = -90;
1559 Enabled = false;
1560 })
1561 Library.ThemeLink(Grad, "Gradient", "AccentDark", "Accent")
1562 Library.ThemeLink(Click, "BackgroundColor3", "SurfaceAlt")
1563
1564 Click.MouseEnter:Connect(function()
1565 Grad.Enabled = true
1566 Tween(Click, { BackgroundColor3 = RGB(255, 255, 255); TextColor3 = RGB(12, 12, 14); TextTransparency = 0 }, 0.12)
1567 end)
1568 Click.MouseLeave:Connect(function()
1569 Grad.Enabled = false
1570 Tween(Click, { BackgroundColor3 = Library.Theme.SurfaceAlt; TextColor3 = Library.Theme.Text; TextTransparency = 0.12 }, 0.12)
1571 end)
1572 Click.Activated:Connect(function()
1573 Button.Callback()
1574 end)
1575
1576 Button.SetText = function(Text: string)
1577 Button.Name = Text
1578 Click.Text = Text
1579 end
1580 Button.Frame = Frame
1581 Button.Click = Click
1582
1583 TIS(Library.Searchable, { Frame = Frame; Text = Button.Name; Section = self })
1584 return Button
1585end
1586
1587Library.Elements.Paragraph = function(self: Library, propertyTable: {})
1588 local Paragraph = Overwrite({
1589 Title = "";
1590 Body = "";
1591 }, propertyTable or {})
1592
1593 local Frame = Add("Frame", {
1594 Parent = self.Content;
1595 Name = "Paragraph";
1596 AutomaticSize = AS.Y;
1597 BackgroundTransparency = 1;
1598 BorderSizePixel = 0;
1599 Size = UFS(1, 0);
1600 })
1601 if Paragraph.Title ~= "" then
1602 Add("TextLabel", {
1603 Parent = Frame;
1604 BackgroundTransparency = 1;
1605 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
1606 Size = UD2(1, 0, 0, 16);
1607 Text = Paragraph.Title;
1608 TextColor3 = RGB(255, 255, 255);
1609 TextSize = 13;
1610 TextTransparency = 0.15;
1611 TextXAlignment = TXA.Left;
1612 })
1613 end
1614 local Body = Add("TextLabel", {
1615 Parent = Frame;
1616 BackgroundTransparency = 1;
1617 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
1618 Position = Paragraph.Title ~= "" and UFO(0, 18) or UFO(0, 0);
1619 AutomaticSize = AS.Y;
1620 Size = UD2(1, 0, 0, 0);
1621 Text = Paragraph.Body;
1622 TextColor3 = RGB(255, 255, 255);
1623 TextSize = 12;
1624 TextTransparency = 0.45;
1625 TextWrapped = true;
1626 TextXAlignment = TXA.Left;
1627 TextYAlignment = TYA.Top;
1628 })
1629 Paragraph.Frame = Frame
1630 Paragraph.SetBody = function(Text: string)
1631 Paragraph.Body = Text
1632 Body.Text = Text
1633 end
1634 Paragraph.SetTitle = function(Text: string)
1635 Paragraph.Title = Text
1636 end
1637
1638 TIS(Library.Searchable, { Frame = Frame; Text = Paragraph.Title .. " " .. Paragraph.Body; Section = self })
1639 return Paragraph
1640end
1641
1642Library.SubElements.Toggle = function(self: Library, propertyTable: {})
1643 local Toggle = Overwrite({
1644 State = false,
1645 Callback = function() end
1646 }, propertyTable or {})
1647
1648 local Button = Add("TextButton", { Parent = self.LeftContent; Name = "Toggle"; AutoButtonColor = false; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxasset://fonts/families/SourceSansPro.json", FW.Regular, FS.Normal); Size = UFO(28, 14); Text = ""; TextColor3 = RGB(0, 0, 0); TextSize = 14; }) :: TextButton
1649 local Indicator = Add("Frame", { Parent = Button; Name = "Indicator"; AnchorPoint = V2(1, 0.5); BackgroundColor3 = RGB(0, 0, 0); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UD2(1, -3, 0.5, 0); Size = UFO(10, 10); ZIndex = 2; }) :: Frame
1650 local Overlay = Add("Frame", { Parent = Button; Name = "Overlay"; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UFS(1, 1); }) :: Frame
1651 Add("UICorner", { Parent = Button; CornerRadius = UD(0, 6); })
1652 Add("UICorner", { Parent = Indicator; CornerRadius = UD(1, 0); })
1653 Add("UICorner", { Parent = Overlay; CornerRadius = UD(0, 6); })
1654 local ToggleGrad = Add("UIGradient", { Parent = Overlay; Color = CS{ CSK(0, Library.Theme.AccentDark), CSK(1, Library.Theme.Accent) }; Rotation = -90; })
1655 Library.ThemeLink(ToggleGrad, "Gradient", "AccentDark", "Accent")
1656
1657 Toggle.Set = function(state: boolean?, Silent: boolean?)
1658 state = state or not Toggle.State
1659 Toggle.State = state
1660
1661 Tween(Overlay, { BackgroundTransparency = state and 0 or 1 }, 0.1)
1662 Tween(Indicator, { Position = state and UD2(1, -3, 0.5, 0) or UD2(0, 3, 0.5, 0), AnchorPoint = state and V2(1, 0.5) or V2(0, 0.5)}, 0.1)
1663
1664 if Toggle.Flag then
1665 Library.Flags[Toggle.Flag] = Library.Flags[Toggle.Flag] or {}
1666 Library.Flags[Toggle.Flag].Value = state
1667 Library.Flags[Toggle.Flag].Set = Toggle.Set
1668 end
1669
1670 if not Silent and Library.NotifyToggles and Library.Notify then
1671 local Label = self.Text or Toggle.Flag or "Toggle"
1672 Library.Notify({
1673 Title = Label;
1674 Text = state and "Enabled" or "Disabled";
1675 Type = state and "Success" or "Info";
1676 Duration = 1.6;
1677 })
1678 end
1679
1680 Toggle.Callback(state)
1681 end
1682
1683 if propertyTable and propertyTable.Flag then
1684 Toggle.Flag = propertyTable.Flag
1685 Library.RegisterFlag(Toggle.Flag, { Value = Toggle.State; Set = Toggle.Set })
1686 end
1687
1688 Button.Activated:Connect(function()
1689 Toggle.Set()
1690 end)
1691
1692 Toggle.Set(Toggle.State, true)
1693 return Toggle
1694end
1695
1696Library.SubElements.Keybind = function(self: Library, propertyTable: {})
1697 local Keybind = Overwrite({
1698 Title = "",
1699 State = false,
1700 Type = "Toggle",
1701 Callback = function() end,
1702 }, propertyTable or {})
1703
1704 local Settings = Add("ImageButton", { Parent = self.RightContent; Name = "Settings"; AutoButtonColor = false; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Image = "rbxassetid://132030186847627"; ImageTransparency = 0.5; ResampleMode = Enum.ResamplerMode.Pixelated; Size = UFO(15, 15); }) :: ImageButton
1705 Keybind.Settings = Settings
1706
1707 local Popup = Add("Frame", { Parent = Library._Instance; Name = "Popup"; Active = true; BackgroundColor3 = RGB(9, 8, 8); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFS(0.3753760755062103, 0.30920326709747314); Size = UFO(180, 119); Visible = false; ZIndex = PopupZ; }) :: Frame
1708 Keybind.Frame = Popup
1709
1710 Add("TextButton", { Parent = Popup; Name = "Catcher"; AutoButtonColor = false; BackgroundTransparency = 1; BorderSizePixel = 0; Size = UFS(1, 1); Text = ""; })
1711 local Header = Add("Frame", { Parent = Popup; Name = "Header"; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(1, 0, 0, 35); }) :: Frame
1712 local Page = Add("Frame", { Parent = Popup; Name = "Page"; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(0, 35); Size = UD2(1, 0, 1, -35); }) :: Frame
1713 local KeyButton = Add("TextButton", { Parent = Page; Name = "KeyButton"; AutoButtonColor = false; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UD2(1, 0, 0, 25); Text = ""; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.5; }) :: TextButton
1714 local Options = Add("Frame", { Parent = Page; Name = "Options"; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(0, 35); Size = UD2(1, 0, 1, -35); }) :: Frame
1715 local HoldButton = Add("TextButton", { Parent = Options; Name = "HoldButton"; AutoButtonColor = false; AutomaticSize = AS.X; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxasset://fonts/families/SourceSansPro.json", FW.Regular, FS.Normal); Size = UFS(0, 1); Text = ""; TextColor3 = RGB(0, 0, 0); TextSize = 14; }) :: TextButton
1716 local ToggleButton = Add("TextButton", { Parent = Options; Name = "ToggleButton"; AutoButtonColor = false; AutomaticSize = AS.X; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxasset://fonts/families/SourceSansPro.json", FW.Regular, FS.Normal); Size = UFS(0, 1); Text = ""; TextColor3 = RGB(0, 0, 0); TextSize = 14; }) :: TextButton
1717 Add("UICorner", { Parent = Popup; CornerRadius = UD(0, 5); })
1718 Add("UIStroke", { Parent = Popup; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
1719 Add("UIShadow", { Parent = Popup; BlurRadius = UD(0, 20); Spread = UFO(5, 5); Transparency = 0.65; })
1720 Add("UICorner", { Parent = Header; BottomLeftRadius = UD(0, 0); BottomRightRadius = UD(0, 0); TopLeftRadius = UD(0, 5); TopRightRadius = UD(0, 5); })
1721 Add("UIStroke", { Parent = Header; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
1722 Add("UIPadding", { Parent = Header; PaddingBottom = UD(0, 10); PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); PaddingTop = UD(0, 10); })
1723 Add("UIListLayout", { Parent = Header; FillDirection = FD.Horizontal; HorizontalFlex = UFA.SpaceBetween; SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
1724 Add("TextLabel", { Parent = Header; Name = "Label"; AnchorPoint = V2(0, 0.5); AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Position = UD2(0, 38, 0.5, 0); Size = UFO(0, 9); Text = Keybind.Title ~= "" and Keybind.Title or self.Text; TextColor3 = RGB(255, 255, 255); TextSize = 13; })
1725 local CloseButton = Add("ImageButton", { Parent = Header; Name = "CloseButton"; AutoButtonColor = false; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Image = "rbxassetid://76308464050634"; Size = UFO(15, 15); }) :: ImageButton
1726 Add("UIStroke", { Parent = KeyButton; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
1727 Add("UICorner", { Parent = KeyButton; CornerRadius = UD(0, 5); })
1728 Add("UIPadding", { Parent = Page; PaddingBottom = UD(0, 12); PaddingLeft = UD(0, 12); PaddingRight = UD(0, 12); PaddingTop = UD(0, 12); })
1729 Add("UIListLayout", { Parent = Options; FillDirection = FD.Horizontal; HorizontalAlignment = HFA.Center; HorizontalFlex = UFA.Fill; Padding = UD(0, 10); SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
1730 local HoldLabel = Add("TextLabel", { Parent = HoldButton; Name = "Label"; AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UFS(1, 1); Text = "Hold"; TextColor3 = RGB(0, 0, 0); TextSize = 14; }) :: TextLabel
1731 Add("UIPadding", { Parent = HoldButton; PaddingLeft = UD(0, 14); PaddingRight = UD(0, 14); })
1732 Add("UICorner", { Parent = HoldButton; CornerRadius = UD(0, 5); })
1733 local HoldGradient = Add("UIGradient", { Parent = HoldButton; Color = CS{ CSK(0, RGB(78, 88, 129)), CSK(1, RGB(138, 156, 229)) }; Rotation = -90; }) :: UIGradient
1734 local ToggleGradient = Add("UIGradient", { Parent = ToggleButton; Color = CS{ CSK(0, RGB(78, 88, 129)), CSK(1, RGB(138, 156, 229)) }; Enabled = false; Rotation = -90; }) :: UIGradient
1735 local ToggleLabel = Add("TextLabel", { Parent = ToggleButton; Name = "Label"; AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UFS(1, 1); Text = "Toggle"; TextColor3 = RGB(255, 255, 255); TextSize = 14; TextTransparency = 0.5; }) :: TextLabel
1736 Add("UIPadding", { Parent = ToggleButton; PaddingLeft = UD(0, 14); PaddingRight = UD(0, 14); })
1737 Add("UICorner", { Parent = ToggleButton; CornerRadius = UD(0, 5); })
1738
1739 local Listening = false
1740
1741 local function Format(Key: EnumItem?): string
1742 if not Key then
1743 return "—"
1744 end
1745 return Keys[Key.Name] or Key.Name
1746 end
1747
1748 local function Matches(Input: InputObject): boolean
1749 return Keybind.Key ~= nil and (Input.KeyCode == Keybind.Key or Input.UserInputType == Keybind.Key)
1750 end
1751
1752 Keybind.Set = function(Key: EnumItem?)
1753 Keybind.Key = Key
1754 KeyButton.Text = Format(Key)
1755 local Title = Keybind.Title ~= "" and Keybind.Title or (self.Text or "Keybind")
1756 Library.KeybindRegistry = Library.KeybindRegistry or {}
1757 Library.KeybindRegistry[Title] = {
1758 Name = Title;
1759 KeyText = Format(Key);
1760 Active = Keybind.State == true;
1761 Mode = Keybind.Type or "Toggle";
1762 }
1763 Library.UpdateKeybindList(Title, Format(Key), Keybind.State, Keybind.Type)
1764 end
1765
1766 Keybind.SetType = function(Type: string)
1767 Keybind.Type = Type
1768 local Held = Type == "Hold"
1769
1770 local function Mode(Button: TextButton, Gradient: UIGradient, Label: TextLabel, Active: boolean)
1771 if Active then
1772 Gradient.Enabled = true
1773 end
1774
1775 local Fade = Tween(Button, { BackgroundColor3 = Active and RGB(255, 255, 255) or RGB(20, 20, 21) }, 0.15)
1776 Tween(Label, { TextColor3 = Active and RGB(0, 0, 0) or RGB(255, 255, 255); TextTransparency = Active and 0 or 0.5 }, 0.15)
1777
1778 if not Active then
1779 Fade.Completed:Once(function()
1780
1781 if Keybind.Type == Type then
1782 Gradient.Enabled = false
1783 end
1784 end)
1785 end
1786 end
1787
1788 Mode(HoldButton, HoldGradient, HoldLabel, Held)
1789 Mode(ToggleButton, ToggleGradient, ToggleLabel, not Held)
1790
1791 if Held and Keybind.State then
1792 Keybind.State = false
1793 Keybind.Callback(false)
1794 end
1795 end
1796
1797 Keybind.Close = function()
1798 Keybind.Open(false)
1799 end
1800
1801 Keybind.Open = function(State: boolean?)
1802 if State == nil then
1803 State = not Popup.Visible
1804 end
1805
1806 if State then
1807 ClaimPopup(Keybind)
1808
1809 local Target = UFO(
1810 Settings.AbsolutePosition.X + Settings.AbsoluteSize.X - Popup.AbsoluteSize.X,
1811 Settings.AbsolutePosition.Y + Settings.AbsoluteSize.Y + 8
1812 )
1813
1814 Popup.Position = Target - UFO(0, 10)
1815 Popup.Visible = true
1816 Tween(Popup, { Position = Target }, 0.25, ES.Quint)
1817 else
1818 Listening = false
1819 Keybind.Set(Keybind.Key)
1820 Popup.Visible = false
1821 ReleasePopup(Keybind)
1822 end
1823
1824 Tween(Settings, { ImageTransparency = State and 0 or 0.5 }, 0.15)
1825 end
1826
1827 KeyButton.Activated:Connect(function()
1828 Listening = true
1829 KeyButton.Text = "..."
1830 end)
1831
1832 HoldButton.Activated:Connect(function()
1833 Keybind.SetType("Hold")
1834 end)
1835
1836 ToggleButton.Activated:Connect(function()
1837 Keybind.SetType("Toggle")
1838 end)
1839
1840 Settings.Activated:Connect(function()
1841 Keybind.Open()
1842 end)
1843
1844 CloseButton.Activated:Connect(function()
1845 Keybind.Open(false)
1846 end)
1847
1848 UserInputService.InputBegan:Connect(function(Input, GameProcessed)
1849 if Listening then
1850
1851 if Input.UserInputType == UIT.MouseButton1 and KeyButton.GuiState ~= EGS.Idle then
1852 return
1853 end
1854
1855 Listening = false
1856
1857 if Input.KeyCode == EKC.Backspace or Input.KeyCode == EKC.Escape then
1858 Keybind.Set(nil)
1859 elseif Input.UserInputType == UIT.Keyboard then
1860 Keybind.Set(Input.KeyCode)
1861 elseif Input.UserInputType == UIT.MouseButton1 or Input.UserInputType == UIT.MouseButton2 or Input.UserInputType == UIT.MouseButton3 then
1862 Keybind.Set(Input.UserInputType)
1863 else
1864 Keybind.Set(Keybind.Key)
1865 end
1866
1867 return
1868 end
1869
1870 if GameProcessed or not Matches(Input) then
1871 return
1872 end
1873
1874 Keybind.State = Keybind.Type == "Hold" or not Keybind.State
1875 local Title = Keybind.Title ~= "" and Keybind.Title or (self.Text or "Keybind")
1876 Library.KeybindRegistry = Library.KeybindRegistry or {}
1877 if Library.KeybindRegistry[Title] then
1878 Library.KeybindRegistry[Title].Active = Keybind.State == true
1879 Library.KeybindRegistry[Title].Mode = Keybind.Type or "Toggle"
1880 end
1881 Library.UpdateKeybindList(Title, Format(Keybind.Key), Keybind.State, Keybind.Type)
1882 Keybind.Callback(Keybind.State)
1883 end)
1884
1885 UserInputService.InputEnded:Connect(function(Input)
1886 if Keybind.Type ~= "Hold" or not Keybind.State or not Matches(Input) then
1887 return
1888 end
1889
1890 Keybind.State = false
1891 local Title = Keybind.Title ~= "" and Keybind.Title or (self.Text or "Keybind")
1892 Library.KeybindRegistry = Library.KeybindRegistry or {}
1893 if Library.KeybindRegistry[Title] then
1894 Library.KeybindRegistry[Title].Active = false
1895 end
1896 Library.UpdateKeybindList(Title, Format(Keybind.Key), false, Keybind.Type)
1897 Keybind.Callback(false)
1898 end)
1899
1900 BindDrag(Popup, Header)
1901
1902 if propertyTable and propertyTable.Flag then
1903 Keybind.Flag = propertyTable.Flag
1904 Library.RegisterFlag(Keybind.Flag, { Value = Keybind.Key; Set = Keybind.Set })
1905 end
1906
1907 Keybind.SetType(Keybind.Type)
1908 Keybind.Set(Keybind.Key)
1909
1910 task.defer(function()
1911 local Title = Keybind.Title ~= "" and Keybind.Title or (self.Text or "Keybind")
1912 Library.UpdateKeybindList(Title, Format(Keybind.Key), false, Keybind.Type)
1913 end)
1914 return Keybind
1915end
1916
1917Library.SubElements.Colorpicker = function(self: Library, propertyTable: {})
1918 local Colorpicker = Overwrite({
1919 Title = "",
1920 Color = RGB(255, 0, 0),
1921 Transparency = 0,
1922 Callback = function() end,
1923 }, propertyTable or {})
1924
1925 local Hue, Saturation, Value = Colorpicker.Color:ToHSV()
1926
1927 local Button = Add("TextButton", { Parent = self.RightContent; Name = "Button"; AutoButtonColor = false; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxasset://fonts/families/SourceSansPro.json", FW.Regular, FS.Normal); Size = UFO(15, 15); Text = ""; TextColor3 = RGB(0, 0, 0); TextSize = 14; }) :: TextButton
1928 Add("UICorner", { Parent = Button; CornerRadius = UD(0, 7); })
1929 Add("UIGradient", { Parent = Button; Color = CS{ CSK(0, RGB(163, 163, 163)), CSK(1, RGB(255, 255, 255)) }; Rotation = -90; })
1930
1931 Colorpicker.Button = Button
1932
1933 local ColorpickerFrame = Add("Frame", { Parent = Library._Instance; Name = "ColorpickerFrame"; Active = true; AutomaticSize = AS.Y; BackgroundColor3 = RGB(9, 8, 8); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFS(0.3759043514728546, 0.058557264506816864); Size = UFO(199, 0); Visible = false; ZIndex = PopupZ; }) :: Frame
1934 Colorpicker.Frame = ColorpickerFrame
1935
1936 Add("TextButton", { Parent = ColorpickerFrame; Name = "Catcher"; AutoButtonColor = false; BackgroundTransparency = 1; BorderSizePixel = 0; Size = UFS(1, 1); Text = ""; })
1937 local Header = Add("Frame", { Parent = ColorpickerFrame; Name = "Header"; BackgroundColor3 = RGB(20, 20, 21); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(1, 0, 0, 35); }) :: Frame
1938
1939 local Page = Add("Frame", { Parent = ColorpickerFrame; Name = "Page"; AutomaticSize = AS.Y; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(0, 35); Size = UD2(1, 0, 0, 0); }) :: Frame
1940 local SaturationBox = Add("Frame", { Parent = Page; Name = "SaturationBox"; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(1, 0, 0, 175); }) :: Frame
1941 local ValueOverlay = Add("Frame", { Parent = SaturationBox; Name = "ValueOverlay"; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UFS(1, 1); }) :: Frame
1942 local SaturationCursor = Add("TextButton", { Parent = SaturationBox; Name = "SaturationCursor"; AnchorPoint = V2(0.5, 0.5); AutoButtonColor = false; BackgroundColor3 = RGB(255, 0, 0); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxasset://fonts/families/SourceSansPro.json", FW.Regular, FS.Normal); Position = UFS(1, 0); Size = UFO(10, 10); Text = ""; TextColor3 = RGB(0, 0, 0); TextSize = 14; }) :: TextButton
1943 local HueSlider = Add("Frame", { Parent = Page; Name = "HueSlider"; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(1, 0, 0, 12); }) :: Frame
1944 local HueCursor = Add("Frame", { Parent = HueSlider; Name = "HueCursor"; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(0, -2); Size = UD2(0, 10, 1, 4); }) :: Frame
1945 local AlphaSlider = Add("Frame", { Parent = Page; Name = "AlphaSlider"; BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(1, 0, 0, 12); }) :: Frame
1946 local AlphaCursor = Add("Frame", { Parent = AlphaSlider; Name = "AlphaCursor"; AnchorPoint = V2(1, 0); BackgroundColor3 = RGB(255, 255, 255); BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UD2(1, 0, 0, -2); Size = UD2(0, 10, 1, 4); }) :: Frame
1947 Add("UICorner", { Parent = ColorpickerFrame; CornerRadius = UD(0, 5); })
1948 Add("UIStroke", { Parent = ColorpickerFrame; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
1949 Add("UIShadow", { Parent = ColorpickerFrame; BlurRadius = UD(0, 20); Spread = UFO(5, 5); Transparency = 0.65; })
1950 Add("UICorner", { Parent = Header; BottomLeftRadius = UD(0, 0); BottomRightRadius = UD(0, 0); TopLeftRadius = UD(0, 5); TopRightRadius = UD(0, 5); })
1951 Add("UIStroke", { Parent = Header; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
1952 Add("UIPadding", { Parent = Header; PaddingBottom = UD(0, 10); PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); PaddingTop = UD(0, 10); })
1953 Add("UIListLayout", { Parent = Header; FillDirection = FD.Horizontal; HorizontalFlex = UFA.SpaceBetween; SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
1954 Add("TextLabel", { Parent = Header; Name = "Label"; AnchorPoint = V2(0, 0.5); AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Position = UD2(0, 38, 0.5, 0); Size = UFO(0, 9); Text = Colorpicker.Title ~= "" and Colorpicker.Title or self.Text; TextColor3 = RGB(255, 255, 255); TextSize = 13; })
1955 local CloseButton = Add("ImageButton", { Parent = Header; Name = "CloseButton"; AutoButtonColor = false; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Image = "rbxassetid://76308464050634"; Size = UFO(15, 15); }) :: ImageButton
1956 Add("UIPadding", { Parent = Page; PaddingBottom = UD(0, 12); PaddingLeft = UD(0, 12); PaddingRight = UD(0, 12); PaddingTop = UD(0, 12); })
1957 Add("UICorner", { Parent = SaturationBox; CornerRadius = UD(0, 5); })
1958 Add("UIGradient", { Parent = ValueOverlay; Color = CS{ CSK(0, RGB(0, 0, 0)), CSK(1, RGB(0, 0, 0)) }; Rotation = -90; Transparency = NS{ NSK(0, 0), NSK(1, 1) }; })
1959 Add("UICorner", { Parent = ValueOverlay; CornerRadius = UD(0, 4); })
1960 local SaturationGradient = Add("UIGradient", { Parent = SaturationBox; Color = CS{ CSK(0, RGB(255, 255, 255)), CSK(1, RGB(255, 0, 0)) }; }) :: UIGradient
1961 Add("UIStroke", { Parent = SaturationBox; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
1962 Add("UICorner", { Parent = SaturationCursor; CornerRadius = UD(1, 0); })
1963 Add("UIShadow", { Parent = SaturationCursor; BlurRadius = UD(0, 5); Spread = UFO(5, 5); Transparency = 0.48; })
1964 Add("UIStroke", { Parent = SaturationCursor; ApplyStrokeMode = ASM.Border; Color = RGB(255, 255, 255); })
1965 Add("UIListLayout", { Parent = Page; Padding = UD(0, 10); SortOrder = SO.LayoutOrder; })
1966 Add("UICorner", { Parent = HueSlider; CornerRadius = UD(0, 5); })
1967 Add("UICorner", { Parent = HueCursor; CornerRadius = UD(0, 3); })
1968 Add("UIShadow", { Parent = HueCursor; BlurRadius = UD(0, 5); Spread = UFO(5, 5); Transparency = 0.48; })
1969 Add("UIGradient", { Parent = HueSlider; Color = CS{ CSK(0, RGB(255, 0, 1)), CSK(0.167, RGB(255, 0, 255)), CSK(0.333, RGB(0, 0, 255)), CSK(0.5, RGB(0, 255, 225)), CSK(0.667, RGB(0, 255, 0)), CSK(0.833, RGB(255, 255, 0)), CSK(1, RGB(255, 0, 0)) }; Transparency = NS{ NSK(0, 0), NSK(0.481, 0.29374998807907104), NSK(1, 0) }; })
1970 Add("UICorner", { Parent = AlphaSlider; CornerRadius = UD(0, 5); })
1971 Add("UICorner", { Parent = AlphaCursor; CornerRadius = UD(0, 3); })
1972 Add("UIShadow", { Parent = AlphaCursor; BlurRadius = UD(0, 5); Spread = UFO(5, 5); Transparency = 0.48; })
1973 local AlphaGradient = Add("UIGradient", { Parent = AlphaSlider; Color = CS{ CSK(0, RGB(255, 255, 255)), CSK(1, RGB(255, 0, 0)) }; }) :: UIGradient
1974
1975 local function Update()
1976 Colorpicker.Color = HSV(Hue, Saturation, Value)
1977
1978 SaturationGradient.Color = CS{ CSK(0, RGB(255, 255, 255)), CSK(1, HSV(Hue, 1, 1)) }
1979 AlphaGradient.Color = CS{ CSK(0, RGB(255, 255, 255)), CSK(1, Colorpicker.Color) }
1980
1981 Tween(SaturationCursor, { Position = UFS(Saturation, 1 - Value), BackgroundColor3 = Colorpicker.Color }, 0.08)
1982 Tween(HueCursor, { AnchorPoint = V2(1 - Hue, 0), Position = UD2(1 - Hue, 0, 0, -2) }, 0.08)
1983 Tween(AlphaCursor, { AnchorPoint = V2(1 - Colorpicker.Transparency, 0), Position = UD2(1 - Colorpicker.Transparency, 0, 0, -2) }, 0.08)
1984
1985 Tween(Button, { BackgroundColor3 = Colorpicker.Color, BackgroundTransparency = Colorpicker.Transparency }, 0.15)
1986
1987 if Colorpicker.Flag and Library.Flags[Colorpicker.Flag] then
1988 Library.Flags[Colorpicker.Flag].Value = Colorpicker.Color
1989 Library.Flags[Colorpicker.Flag].Transparency = Colorpicker.Transparency
1990 end
1991
1992 Colorpicker.Callback(Colorpicker.Color, Colorpicker.Transparency)
1993 end
1994
1995 Colorpicker.Set = function(Color: Color3?, Transparency: number?)
1996 if Color then
1997 Hue, Saturation, Value = Color:ToHSV()
1998 end
1999
2000 Colorpicker.Transparency = MC(Transparency or Colorpicker.Transparency, 0, 1)
2001 Update()
2002 end
2003
2004 Colorpicker.Close = function()
2005 Colorpicker.Toggle(false)
2006 end
2007
2008 Colorpicker.Toggle = function(State: boolean?)
2009 if State == nil then
2010 State = not ColorpickerFrame.Visible
2011 end
2012
2013 if State then
2014 ClaimPopup(Colorpicker)
2015
2016 local Target = UFO(
2017 Button.AbsolutePosition.X + Button.AbsoluteSize.X - ColorpickerFrame.AbsoluteSize.X,
2018 Button.AbsolutePosition.Y + Button.AbsoluteSize.Y + 8
2019 )
2020
2021 ColorpickerFrame.Position = Target - UFO(0, 10)
2022 ColorpickerFrame.Visible = true
2023 Tween(ColorpickerFrame, { Position = Target }, 0.25, ES.Quint)
2024 else
2025 ColorpickerFrame.Visible = false
2026 ReleasePopup(Colorpicker)
2027 end
2028 end
2029
2030 BindSlider(HueSlider, function(Alpha)
2031 Hue = 1 - Alpha.X
2032 Update()
2033 end)
2034
2035 BindSlider(SaturationBox, function(Alpha)
2036 Saturation, Value = Alpha.X, 1 - Alpha.Y
2037 Update()
2038 end)
2039
2040 BindSlider(AlphaSlider, function(Alpha)
2041 Colorpicker.Transparency = 1 - Alpha.X
2042 Update()
2043 end)
2044
2045 Button.Activated:Connect(function()
2046 Colorpicker.Toggle()
2047 end)
2048
2049 CloseButton.Activated:Connect(function()
2050 Colorpicker.Toggle(false)
2051 end)
2052
2053 BindDrag(ColorpickerFrame, Header)
2054
2055 if propertyTable and propertyTable.Flag then
2056 Colorpicker.Flag = propertyTable.Flag
2057 Library.RegisterFlag(Colorpicker.Flag, {
2058 Value = Colorpicker.Color;
2059 Transparency = Colorpicker.Transparency;
2060 Set = Colorpicker.Set;
2061 })
2062 end
2063
2064 Colorpicker.Set(Colorpicker.Color, Colorpicker.Transparency)
2065 return Colorpicker
2066end
2067
2068Library._Instance = Add("ScreenGui", { Parent = RunService:IsStudio() and Client.PlayerGui or Services:GetService("CoreGui"); Name = "Window"; ZIndexBehavior = ZIB.Sibling; }) :: ScreenGui
2069
2070Library.Window = function(self: Library, propertyTable: {})
2071 local Window = Overwrite({
2072 Title = "",
2073 Footer = "",
2074 Logo = nil,
2075 Icon = nil,
2076 }, propertyTable or {})
2077
2078 local Canvas = Add("Frame", { Parent = self._Instance; Name = "Canvas"; BackgroundColor3 = Library.Theme.Background; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UFO(658, 461); }) :: Frame
2079 Library.ThemeLink(Canvas, "BackgroundColor3", "Background")
2080 local Sidebar = Add("Frame", { Parent = Canvas; Name = "Sidebar"; BackgroundColor3 = Library.Theme.Surface; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UD2(0, 75, 1, 0); }) :: Frame
2081 Library.ThemeLink(Sidebar, "BackgroundColor3", "Surface")
2082
2083 -- Author logo (top left) with top padding from window edge
2084 local LogoWrap = Add("Frame", {
2085 Parent = Sidebar;
2086 Name = "Logo";
2087 BackgroundTransparency = 1;
2088 Size = UD2(1, 0, 0, 58);
2089 BorderSizePixel = 0;
2090 })
2091 Add("UIPadding", {
2092 Parent = LogoWrap;
2093 PaddingTop = UD(0, 10);
2094 })
2095 local LogoBtn = Add("ImageLabel", {
2096 Parent = LogoWrap;
2097 AnchorPoint = V2(0.5, 0.5);
2098 Position = UFS(0.5, 0.55);
2099 Size = UFO(32, 32);
2100 BackgroundTransparency = 1;
2101 Image = ResolveIcon(Window.Logo or Window.Icon or "hash");
2102 ImageColor3 = RGB(255, 255, 255);
2103 ImageTransparency = 0;
2104 ScaleType = SCL.Fit;
2105 ZIndex = 3;
2106 })
2107 local LogoGlow = Add("ImageLabel", {
2108 Parent = LogoWrap;
2109 AnchorPoint = V2(0.5, 0.5);
2110 Position = UFS(0.5, 0.55);
2111 Size = UFO(64, 64);
2112 BackgroundTransparency = 1;
2113 Image = "rbxassetid://8992230677";
2114 ImageColor3 = Library.Theme.Accent;
2115 ImageTransparency = 0.75;
2116 ZIndex = 1;
2117 })
2118 Library.ThemeLink(LogoGlow, "ImageColor3", "Accent")
2119 local LogoGlow2 = Add("ImageLabel", {
2120 Parent = LogoWrap;
2121 AnchorPoint = V2(0.5, 0.5);
2122 Position = UFS(0.5, 0.55);
2123 Size = UFO(42, 42);
2124 BackgroundTransparency = 1;
2125 Image = "rbxassetid://8992230677";
2126 ImageColor3 = Library.Theme.Accent;
2127 ImageTransparency = 0.88;
2128 ZIndex = 2;
2129 })
2130 Library.ThemeLink(LogoGlow2, "ImageColor3", "Accent")
2131 Window.LogoImage = LogoBtn
2132 Window.SetLogo = function(_, Icon)
2133 LogoBtn.Image = ResolveIcon(Icon)
2134 end
2135
2136 local PageButtons = Add("ScrollingFrame", {
2137 Parent = Sidebar;
2138 Name = "PageButtons";
2139 BackgroundTransparency = 1;
2140 BorderSizePixel = 0;
2141 Position = UFO(0, 58);
2142 Size = UD2(1, 0, 1, -58);
2143 CanvasSize = UD2(0, 0, 0, 0);
2144 AutomaticCanvasSize = AS.Y;
2145 ScrollBarThickness = 0;
2146 ScrollingDirection = SBD.Y;
2147 ClipsDescendants = true;
2148 Active = true;
2149 Selectable = false;
2150 })
2151 Add("UIListLayout", {
2152 Parent = PageButtons;
2153 Padding = UD(0, 5);
2154 HorizontalAlignment = HFA.Center;
2155 SortOrder = SO.LayoutOrder;
2156 })
2157
2158 Window.TabEditMode = false
2159 -- Very small lock/reorder toggle
2160 local EditRow = Add("Frame", {
2161 Parent = Sidebar;
2162 Name = "TabEdit";
2163 AnchorPoint = V2(0.5, 1);
2164 Position = UD2(0.5, 0, 1, -6);
2165 Size = UFO(22, 10);
2166 BackgroundTransparency = 1;
2167 ZIndex = 5;
2168 })
2169 local EditTrack = Add("Frame", {
2170 Parent = EditRow;
2171 Size = UFS(1, 1);
2172 BackgroundColor3 = Library.Theme.SurfaceAlt;
2173 BorderSizePixel = 0;
2174 })
2175 Add("UICorner", { Parent = EditTrack; CornerRadius = UD(1, 0); })
2176 Library.ThemeLink(EditTrack, "BackgroundColor3", "SurfaceAlt")
2177 local EditKnob = Add("Frame", {
2178 Parent = EditTrack;
2179 Size = UFO(8, 8);
2180 Position = UD2(0, 1, 0.5, 0);
2181 AnchorPoint = V2(0, 0.5);
2182 BackgroundColor3 = RGB(140, 144, 155);
2183 BorderSizePixel = 0;
2184 ZIndex = 6;
2185 })
2186 Add("UICorner", { Parent = EditKnob; CornerRadius = UD(1, 0); })
2187 local EditHit = Add("TextButton", {
2188 Parent = EditRow;
2189 Size = UFS(1, 1);
2190 BackgroundTransparency = 1;
2191 Text = "";
2192 ZIndex = 7;
2193 })
2194 EditHit.Activated:Connect(function()
2195 Window.TabEditMode = not Window.TabEditMode
2196 local On = Window.TabEditMode
2197 Tween(EditKnob, {
2198 Position = On and UD2(1, -1, 0.5, 0) or UD2(0, 1, 0.5, 0);
2199 AnchorPoint = On and V2(1, 0.5) or V2(0, 0.5);
2200 BackgroundColor3 = On and Library.Theme.Accent or RGB(180, 184, 200);
2201 }, 0.12)
2202 Tween(EditTrack, {
2203 BackgroundColor3 = On and Library.Theme.AccentDark or Library.Theme.SurfaceAlt;
2204 }, 0.12)
2205 Library.Notify({
2206 Title = "Tabs";
2207 Text = On and "Drag tabs to rearrange" or "Tab order locked";
2208 Type = "Info";
2209 Duration = 1.5;
2210 })
2211 end)
2212 Window.TabEditButton = EditHit
2213 PageButtons.Size = UD2(1, 0, 1, -58 - 28)
2214 local Header = Add("Frame", { Parent = Canvas; Name = "Header"; BackgroundColor3 = Library.Theme.SurfaceAlt; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(75, 0); Size = UD2(1, -75, 0, 50); }) :: Frame
2215 Library.ThemeLink(Header, "BackgroundColor3", "SurfaceAlt")
2216 local SubPages = Add("Frame", { Parent = Header; Name = "SubPages"; AutomaticSize = AS.X; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Size = UFS(0, 1); }) :: Frame
2217 local Search = Add("Frame", { Parent = Header; Name = "Search"; LayoutOrder = 1; Active = true; AnchorPoint = V2(1, 0); AutomaticSize = AS.X; BackgroundColor3 = Library.Theme.Background; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFS(1, 0); Selectable = true; Size = UD2(0, 200, 1, 0); }) :: Frame
2218 local Pages = Add("Frame", { Parent = Canvas; Name = "Pages"; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UFO(75, 50); Size = UD2(1, -75, 1, -75); }) :: Frame
2219 local Footer = Add("Frame", { Parent = Canvas; Name = "Footer"; AnchorPoint = V2(0, 1); BackgroundColor3 = Library.Theme.Surface; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Position = UD2(0, 75, 1, 0); Size = UD2(1, -75, 0, 25); }) :: Frame
2220 Library.ThemeLink(Footer, "BackgroundColor3", "Surface")
2221 local SearchBox = Add("TextBox", { Parent = Search; Name = "TextLabel"; Active = false; AutomaticSize = AS.X; ClearTextOnFocus = false; LayoutOrder = 1; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); PlaceholderColor3 = RGB(255, 255, 255); PlaceholderText = "Search function"; Selectable = false; Size = UFS(0, 1); Text = ""; TextColor3 = RGB(255, 255, 255); TextSize = 14; TextTransparency = 0.5; }) :: TextBox
2222 Add("UIStroke", { Parent = Canvas; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
2223 Add("UICorner", { Parent = Canvas; CornerRadius = UD(0, 5); })
2224 Add("UICorner", { Parent = Sidebar; BottomLeftRadius = UD(0, 5); BottomRightRadius = UD(0, 0); TopLeftRadius = UD(0, 5); TopRightRadius = UD(0, 0); })
2225 Add("UIStroke", { Parent = Sidebar; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
2226 Add("UICorner", { Parent = Header; BottomLeftRadius = UD(0, 0); BottomRightRadius = UD(0, 0); TopLeftRadius = UD(0, 0); TopRightRadius = UD(0, 5); })
2227 Add("UIStroke", { Parent = Header; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
2228 Add("UIListLayout", { Parent = SubPages; FillDirection = FD.Horizontal; Padding = UD(0, 10); SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
2229 Add("UIPadding", { Parent = Header; PaddingBottom = UD(0, 10); PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); PaddingTop = UD(0, 10); })
2230 Add("UIPadding", { Parent = Search; PaddingLeft = UD(0, 8); PaddingRight = UD(0, 8); })
2231 Add("UICorner", { Parent = Search; CornerRadius = UD(0, 5); })
2232 Add("UIListLayout", { Parent = Search; FillDirection = FD.Horizontal; Padding = UD(0, 5); SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
2233 Add("ImageLabel", { Parent = Search; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; LayoutOrder = 0; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; Image = "rbxassetid://82536262318754"; ImageTransparency = 0.5; ResampleMode = Enum.ResamplerMode.Pixelated; Size = UFO(15, 15); })
2234 Add("UIListLayout", { Parent = Header; FillDirection = FD.Horizontal; HorizontalFlex = UFA.SpaceBetween; SortOrder = SO.LayoutOrder; VerticalAlignment = VFA.Center; })
2235 Add("UIPadding", { Parent = Pages; PaddingBottom = UD(0, 12); PaddingLeft = UD(0, 12); PaddingRight = UD(0, 12); PaddingTop = UD(0, 12); })
2236 Add("UIShadow", { Parent = Canvas; BlurRadius = UD(0, 20); Spread = UFO(5, 5); Transparency = 0.65; })
2237 Add("UICorner", { Parent = Footer; BottomLeftRadius = UD(0, 0); BottomRightRadius = UD(0, 5); TopLeftRadius = UD(0, 0); TopRightRadius = UD(0, 0); })
2238 Add("UIStroke", { Parent = Footer; ApplyStrokeMode = ASM.Border; Color = RGB(36, 37, 37); })
2239 Add("UIPadding", { Parent = Footer; PaddingBottom = UD(0, 10); PaddingLeft = UD(0, 10); PaddingRight = UD(0, 10); PaddingTop = UD(0, 10); })
2240 Add("TextLabel", { Parent = Footer; AnchorPoint = V2(0, 0.5); AutomaticSize = AS.X; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Position = UFS(0, 0.5); Size = UFO(0, 13); Text = Window.Title; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.5; })
2241 Add("TextLabel", { Parent = Footer; AnchorPoint = V2(1, 0.5); AutomaticSize = AS.X; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Position = UFS(1, 0.5); Size = UFO(0, 13); Text = Window.Footer; TextColor3 = RGB(255, 255, 255); TextSize = 13; TextTransparency = 0.5; })
2242 BindDrag(Canvas, Header, true, Search)
2243
2244 Window.Canvas = Canvas
2245 TIS(Library.Windows, Window)
2246 Add("UIScale", { Parent = Canvas; Scale = Library.UIScale })
2247
2248 local function CenterCanvas()
2249 local Camera = workspace.CurrentCamera
2250 if not Camera or not Canvas.Parent then
2251 return
2252 end
2253 local Viewport = Camera.ViewportSize
2254 local W, H = 658, 461
2255 local Scale = Library.UIScale or 1
2256 local GuiService = Services:GetService("GuiService")
2257 local Inset = GuiService:GetGuiInset()
2258 local X = math.floor((Viewport.X - W * Scale) * 0.5)
2259 local Y = math.floor((Viewport.Y - Inset.Y - H * Scale) * 0.5)
2260 Canvas.Position = ClampToScreen(Canvas, UFO(math.max(4, X), math.max(4, Y)))
2261 end
2262 CenterCanvas()
2263 task.defer(CenterCanvas)
2264 task.delay(0.05, CenterCanvas)
2265
2266 Library.SetWatermark(Library.Watermark.Text, Library.Watermark.Enabled)
2267 Library.SetKeybindList(Library.KeybindList.Enabled)
2268 if Library._MountKeySystem then
2269 Library._MountKeySystem(Window)
2270 end
2271 task.defer(CenterCanvas)
2272
2273 do
2274 local Cam = workspace.CurrentCamera
2275 if Cam then
2276 Cam:GetPropertyChangedSignal("ViewportSize"):Connect(function()
2277 if Canvas and Canvas.Parent then
2278 Canvas.Position = ClampToScreen(Canvas, Canvas.Position)
2279 end
2280 end)
2281 end
2282 end
2283
2284 Search.InputBegan:Connect(function(Input)
2285 if Input.UserInputType == UIT.MouseButton1 or Input.UserInputType == UIT.Touch then
2286 SearchBox:CaptureFocus()
2287 end
2288 end)
2289
2290 SearchBox:GetPropertyChangedSignal("Text"):Connect(function()
2291 local Query = SearchBox.Text:lower()
2292 local Matched = {}
2293 local FirstOwner = nil
2294
2295 for _, Entry in Library.Searchable do
2296 local Visible = Query == "" or Entry.Text:lower():find(Query, 1, true) ~= nil
2297 Entry.Frame.Visible = Visible
2298
2299 if Visible then
2300 Matched[Entry.Section] = true
2301 if Query ~= "" and not FirstOwner and Entry.Section and Entry.Section.PageFrame then
2302 FirstOwner = (Library.PageFrames or {})[Entry.Section.PageFrame]
2303 end
2304 end
2305 end
2306
2307 for _, Section in Library.Sections do
2308 Section.Frame.Visible = Query == "" or Matched[Section] == true
2309 end
2310
2311 if Query ~= "" and FirstOwner then
2312 local Owner = FirstOwner
2313 if Owner.ParentPage then
2314 if not Owner.ParentPage.IsOpen then
2315 Owner.ParentPage.Open()
2316 end
2317 if not Owner.IsOpen then
2318 Owner.Open()
2319 end
2320 elseif not Owner.IsOpen then
2321 Owner.Open()
2322 end
2323 end
2324 end)
2325
2326 Window.Pages = {}
2327 Window.Page = function(self: Library, propertyTable: {})
2328 local Page = Overwrite({
2329 Icon = "box"
2330 }, propertyTable or {})
2331
2332 Page.SubPages = {}
2333 Page.ActiveSubPage = nil
2334 Page.Opened = false
2335
2336 local PageButton = Add("TextButton", {
2337 Parent = PageButtons;
2338 Name = "PageButton";
2339 AutoButtonColor = false;
2340 BackgroundTransparency = 1;
2341 BorderSizePixel = 0;
2342 Size = UFO(45, 45);
2343 Text = "";
2344 ClipsDescendants = false;
2345 LayoutOrder = #Window.Pages;
2346 }) :: TextButton
2347
2348 -- Soft radial selection bloom (centered behind icon)
2349 local GlowImage = Add("ImageLabel", {
2350 Parent = PageButton;
2351 Name = "GlowImage";
2352 AnchorPoint = V2(0.5, 0.5);
2353 Position = UFS(0.5, 0.5);
2354 Size = UFO(52, 52);
2355 BackgroundTransparency = 1;
2356 Image = "rbxassetid://8992230677";
2357 ImageColor3 = Library.Theme.Accent;
2358 ImageTransparency = 1;
2359 ZIndex = 1;
2360 BorderSizePixel = 0;
2361 })
2362 Library.ThemeLink(GlowImage, "ImageColor3", "Accent")
2363 local GlowInner = Add("ImageLabel", {
2364 Parent = PageButton;
2365 Name = "GlowInner";
2366 AnchorPoint = V2(0.5, 0.5);
2367 Position = UFS(0.5, 0.5);
2368 Size = UFO(36, 36);
2369 BackgroundTransparency = 1;
2370 Image = "rbxassetid://8992230677";
2371 ImageColor3 = Library.Theme.Accent;
2372 ImageTransparency = 1;
2373 ZIndex = 2;
2374 BorderSizePixel = 0;
2375 })
2376 Library.ThemeLink(GlowInner, "ImageColor3", "Accent")
2377
2378 local PageIcon = Add("ImageLabel", {
2379 Parent = PageButton;
2380 BackgroundTransparency = 1;
2381 BorderSizePixel = 0;
2382 Image = ResolveIcon(Page.Icon);
2383 ImageTransparency = 0.45;
2384 ImageColor3 = RGB(255, 255, 255);
2385 ScaleType = SCL.Fit;
2386 Size = UFS(1, 1);
2387 ZIndex = 3;
2388 }) :: ImageLabel
2389 Add("UIPadding", {
2390 Parent = PageButton;
2391 PaddingBottom = UD(0, 12);
2392 PaddingLeft = UD(0, 12);
2393 PaddingRight = UD(0, 12);
2394 PaddingTop = UD(0, 12);
2395 })
2396
2397 Page.Button = PageButton
2398 Page.GlowImage = GlowImage
2399 Page.GlowInner = GlowInner
2400 Page.IconLabel = PageIcon
2401 Page.LayoutOrder = PageButton.LayoutOrder
2402
2403 PageContent(Page, Pages, Window.Pages, function()
2404 Page.Opened = true
2405 Tween(GlowImage, { ImageTransparency = 0.62 }, 0.22)
2406 Tween(GlowInner, { ImageTransparency = 0.78 }, 0.22)
2407 Tween(PageIcon, { ImageTransparency = 0, ImageColor3 = Library.Theme.Accent }, 0.2)
2408
2409 for _, SubPage in Page.SubPages do
2410 SubPage.Button.Visible = true
2411 end
2412
2413 if Page.ActiveSubPage then
2414 Page.Frame.Visible = false
2415 Page.ActiveSubPage.Open()
2416 end
2417 end, function()
2418 Page.Opened = false
2419 Tween(GlowImage, { ImageTransparency = 1 }, 0.16)
2420 Tween(GlowInner, { ImageTransparency = 1 }, 0.16)
2421 Tween(PageIcon, { ImageTransparency = 0.45, ImageColor3 = RGB(255, 255, 255) }, 0.16)
2422
2423 for _, SubPage in Page.SubPages do
2424 SubPage.Button.Visible = false
2425 end
2426
2427 if Page.ActiveSubPage then
2428 Page.ActiveSubPage.Close()
2429 end
2430 end)
2431
2432 -- Drag-reorder: ghost snaps in-list only
2433 do
2434 local Dragging = false
2435 local Ghost = nil
2436 local Placeholder = nil
2437
2438 local function ClearGhost()
2439 if Ghost then pcall(function() Ghost:Destroy() end) Ghost = nil end
2440 if Placeholder then pcall(function() Placeholder:Destroy() end) Placeholder = nil end
2441 end
2442
2443 local function OrderedPages()
2444 local List = {}
2445 for _, P in Window.Pages do
2446 if P ~= Page and P.Button and P.Button.Parent then
2447 TIS(List, P)
2448 end
2449 end
2450 table.sort(List, function(a, b)
2451 return (a.Button.LayoutOrder or 0) < (b.Button.LayoutOrder or 0)
2452 end)
2453 return List
2454 end
2455
2456 local function ApplyInsert(InsertIndex)
2457 local List = OrderedPages()
2458 InsertIndex = MC(InsertIndex, 0, #List)
2459 if Placeholder then
2460 Placeholder.LayoutOrder = InsertIndex * 2
2461 end
2462 for Index, P in List do
2463 local Slot = Index - 1
2464 if Slot >= InsertIndex then
2465 Slot = Slot + 1
2466 end
2467 P.Button.LayoutOrder = Slot * 2
2468 P.LayoutOrder = P.Button.LayoutOrder
2469 end
2470 end
2471
2472 PageButton.InputBegan:Connect(function(Input)
2473 if not Window.TabEditMode then return end
2474 if Input.UserInputType ~= UIT.MouseButton1 and Input.UserInputType ~= UIT.Touch then return end
2475 if Dragging then return end
2476 Dragging = true
2477 local OriginOrder = PageButton.LayoutOrder
2478
2479 ClearGhost()
2480 PageButton.Visible = false
2481
2482 -- Outline-only slot (no solid blue fill)
2483 Placeholder = Add("Frame", {
2484 Parent = PageButtons;
2485 Name = "TabPlaceholder";
2486 Size = UFO(45, 45);
2487 BackgroundTransparency = 1;
2488 BorderSizePixel = 0;
2489 LayoutOrder = OriginOrder;
2490 })
2491 local PhStroke = Add("UIStroke", {
2492 Parent = Placeholder;
2493 Color = Library.Theme.Accent;
2494 Transparency = 0.35;
2495 Thickness = 1.5;
2496 })
2497 Add("UICorner", { Parent = Placeholder; CornerRadius = UD(0, 8); })
2498
2499 Ghost = Add("Frame", {
2500 Parent = Library._Instance;
2501 Name = "TabGhost";
2502 Size = UFO(45, 45);
2503 BackgroundTransparency = 1;
2504 ZIndex = 120;
2505 })
2506 Add("ImageLabel", {
2507 Parent = Ghost;
2508 BackgroundTransparency = 1;
2509 Size = UFS(1, 1);
2510 Image = PageIcon.Image;
2511 ImageColor3 = Library.Theme.Accent;
2512 ImageTransparency = 0.2;
2513 ScaleType = SCL.Fit;
2514 })
2515 Add("UIPadding", {
2516 Parent = Ghost;
2517 PaddingBottom = UD(0, 12);
2518 PaddingLeft = UD(0, 12);
2519 PaddingRight = UD(0, 12);
2520 PaddingTop = UD(0, 12);
2521 })
2522
2523 local function ClampGhostY(MouseY)
2524 local Top = PageButtons.AbsolutePosition.Y
2525 local Bot = Top + PageButtons.AbsoluteSize.Y - 45
2526 local GX = PageButtons.AbsolutePosition.X + (PageButtons.AbsoluteSize.X - 45) * 0.5
2527 local GY = MC(MouseY - 22, Top, math.max(Top, Bot))
2528 return GX, GY
2529 end
2530
2531 local Abs = PageButton.AbsolutePosition
2532 local GX, GY = ClampGhostY(Abs.Y + 22)
2533 Ghost.Position = UFO(GX, GY)
2534
2535 local MoveConn
2536 local EndConn
2537 MoveConn = UserInputService.InputChanged:Connect(function(Move)
2538 if not Dragging then return end
2539 if Move.UserInputType ~= UIT.MouseMovement and Move.UserInputType ~= UIT.Touch then return end
2540 local gx, gy = ClampGhostY(Move.Position.Y)
2541 if Ghost then
2542 Ghost.Position = UFO(gx, gy)
2543 end
2544 local List = OrderedPages()
2545 local Insert = #List
2546 for Index, P in List do
2547 local Mid = P.Button.AbsolutePosition.Y + P.Button.AbsoluteSize.Y * 0.5
2548 if Move.Position.Y < Mid then
2549 Insert = Index - 1
2550 break
2551 end
2552 Insert = Index
2553 end
2554 ApplyInsert(Insert)
2555 end)
2556 EndConn = UserInputService.InputEnded:Connect(function(End)
2557 if End.UserInputType ~= UIT.MouseButton1 and End.UserInputType ~= UIT.Touch then return end
2558 if not Dragging then return end
2559 Dragging = false
2560 if MoveConn then MoveConn:Disconnect() end
2561 if EndConn then EndConn:Disconnect() end
2562 local FinalOrder = Placeholder and Placeholder.LayoutOrder or OriginOrder
2563 ClearGhost()
2564 PageButton.Visible = true
2565 PageButton.LayoutOrder = FinalOrder
2566 Page.LayoutOrder = FinalOrder
2567 local All = {}
2568 for _, P in Window.Pages do
2569 if P.Button and P.Button.Parent then
2570 TIS(All, P)
2571 end
2572 end
2573 table.sort(All, function(a, b)
2574 return (a.Button.LayoutOrder or 0) < (b.Button.LayoutOrder or 0)
2575 end)
2576 for Index, P in All do
2577 P.Button.LayoutOrder = Index - 1
2578 P.LayoutOrder = Index - 1
2579 end
2580 pcall(function() Library.SaveLayout() end)
2581 end)
2582 end)
2583 end
2584
2585 Page.SubPage = function(self: Library, propertyTable: {})
2586 local SubPage = Overwrite({
2587 Name = "",
2588 }, propertyTable or {})
2589
2590 local SubPageButton = Add("TextButton", { Parent = SubPages; Name = "SubPageButton"; AutoButtonColor = false; AutomaticSize = AS.X; BackgroundColor3 = Library.Theme.Background; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxasset://fonts/families/SourceSansPro.json", FW.Regular, FS.Normal); Size = UFS(0, 1); Text = ""; TextColor3 = RGB(0, 0, 0); TextSize = 14; Visible = Page.Opened; }) :: TextButton
2591 local SubGrad = Add("UIGradient", { Parent = SubPageButton; Color = CS{ CSK(0, Library.Theme.AccentDark), CSK(1, Library.Theme.Accent) }; Rotation = -70; })
2592 Library.ThemeLink(SubGrad, "Gradient", "AccentDark", "Accent")
2593 local SubPageLabel = Add("TextLabel", { Parent = SubPageButton; Name = "Label"; AutomaticSize = AS.XY; BackgroundColor3 = RGB(255, 255, 255); BackgroundTransparency = 1; BorderColor3 = RGB(0, 0, 0); BorderSizePixel = 0; FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal); Size = UFS(1, 1); Text = SubPage.Name; TextColor3 = RGB(255, 255, 255); TextSize = 14; TextTransparency = 0.5; }) :: TextLabel
2594 Add("UIPadding", { Parent = SubPageButton; PaddingLeft = UD(0, 14); PaddingRight = UD(0, 14); })
2595 Add("UICorner", { Parent = SubPageButton; CornerRadius = UD(0, 5); })
2596
2597 SubPage.Button = SubPageButton
2598
2599 SubPage.ParentPage = Page
2600 PageContent(SubPage, Pages, Page.SubPages, function()
2601
2602 Page.ActiveSubPage = SubPage
2603 Page.Frame.Visible = false
2604
2605 Tween(SubPageButton, { BackgroundColor3 = RGB(255, 255, 255) }, 0.15)
2606 Tween(SubPageLabel, { TextTransparency = 0 }, 0.15)
2607 end, function()
2608 Tween(SubPageButton, { BackgroundColor3 = Library.Theme.Background }, 0.15)
2609 Tween(SubPageLabel, { TextTransparency = 0.5 }, 0.15)
2610 end)
2611
2612 SubPageButton.Activated:Connect(SubPage.Open)
2613
2614 if #Page.SubPages == 1 then
2615 Page.ActiveSubPage = SubPage
2616
2617 if Page.Opened then
2618 SubPage.Open()
2619 end
2620 else
2621 SubPage.Close()
2622 end
2623
2624 return SubPage
2625 end
2626
2627 PageButton.Activated:Connect(Page.Open)
2628
2629 if #Window.Pages == 1 then
2630 Page.Open()
2631 else
2632 Page.Close()
2633 end
2634
2635 return Page
2636 end
2637
2638 return Window
2639end
2640
2641Library.Theme = {
2642 Accent = RGB(138, 156, 229),
2643 AccentDark = RGB(78, 88, 129),
2644 Background = RGB(9, 8, 8),
2645 Surface = RGB(15, 14, 15),
2646 SurfaceAlt = RGB(20, 20, 21),
2647 Border = RGB(36, 37, 37),
2648 SectionBorder = RGB(32, 33, 36),
2649 Text = RGB(255, 255, 255),
2650 TextDim = RGB(180, 184, 200),
2651}
2652
2653Library.DefaultTheme = {
2654 Accent = RGB(138, 156, 229),
2655 AccentDark = RGB(78, 88, 129),
2656 Background = RGB(9, 8, 8),
2657 Surface = RGB(15, 14, 15),
2658 SurfaceAlt = RGB(20, 20, 21),
2659 Border = RGB(36, 37, 37),
2660 SectionBorder = RGB(32, 33, 36),
2661 Text = RGB(255, 255, 255),
2662 TextDim = RGB(180, 184, 200),
2663}
2664
2665Library.ThemeLinks = {}
2666
2667Library.ThemeLink = function(Object: Instance, Property: string, Key: string, Key2: string?)
2668 if not Object then
2669 return
2670 end
2671 TIS(Library.ThemeLinks, { Object = Object; Property = Property; Key = Key; Key2 = Key2 })
2672end
2673
2674Library.ApplyTheme = function()
2675 local T = Library.Theme
2676 if not T then
2677 return
2678 end
2679
2680 -- Always derive AccentDark from Accent when accent changes
2681 if T.Accent then
2682 local H, S, V = T.Accent:ToHSV()
2683 T.AccentDark = HSV(H, math.clamp(S * 0.95, 0, 1), math.max(V * 0.55, 0.12))
2684 end
2685
2686 local function PaintGrad(Grad: UIGradient?)
2687 if Grad and Grad:IsA("UIGradient") then
2688 Grad.Color = CS{ CSK(0, T.AccentDark or T.Accent), CSK(1, T.Accent) }
2689 end
2690 end
2691
2692 -- ThemeLink registry
2693 local Alive = {}
2694 for _, Link in Library.ThemeLinks do
2695 if Link.Object and Link.Object.Parent then
2696 TIS(Alive, Link)
2697 if Link.Property == "Gradient" and Link.Object:IsA("UIGradient") then
2698 PaintGrad(Link.Object)
2699 elseif Link.Property and T[Link.Key] ~= nil then
2700 pcall(function()
2701 Link.Object[Link.Property] = T[Link.Key]
2702 end)
2703 end
2704 end
2705 end
2706 Library.ThemeLinks = Alive
2707
2708 for _, Win in Library.Windows do
2709 local Canvas = Win.Canvas
2710 if not Canvas then
2711 continue
2712 end
2713 pcall(function() Canvas.BackgroundColor3 = T.Background end)
2714 local Stroke = Canvas:FindFirstChildOfClass("UIStroke")
2715 if Stroke then pcall(function() Stroke.Color = T.Border end) end
2716
2717 local Header = Canvas:FindFirstChild("Header")
2718 if Header then
2719 Header.BackgroundColor3 = T.SurfaceAlt
2720 local Hs = Header:FindFirstChildOfClass("UIStroke")
2721 if Hs then Hs.Color = T.Border end
2722 local Search = Header:FindFirstChild("Search")
2723 if Search and Search:IsA("GuiObject") then
2724 Search.BackgroundColor3 = T.Background
2725 end
2726 end
2727 local Footer = Canvas:FindFirstChild("Footer")
2728 if Footer then
2729 Footer.BackgroundColor3 = T.Surface
2730 local Fs = Footer:FindFirstChildOfClass("UIStroke")
2731 if Fs then Fs.Color = T.Border end
2732 for _, L in Footer:GetChildren() do
2733 if L:IsA("TextLabel") then
2734 L.TextColor3 = T.Text
2735 end
2736 end
2737 end
2738 local Sidebar = Canvas:FindFirstChild("Sidebar")
2739 if Sidebar then
2740 Sidebar.BackgroundColor3 = T.Surface
2741 local Logo = Sidebar:FindFirstChild("Logo")
2742 if Logo then
2743 for _, Ch in Logo:GetChildren() do
2744 if Ch:IsA("ImageLabel") then
2745 Ch.ImageColor3 = T.Accent
2746 end
2747 end
2748 end
2749 local PB = Sidebar:FindFirstChild("PageButtons")
2750 if PB and PB:IsA("ScrollingFrame") then
2751 PB.ScrollBarImageColor3 = T.Accent
2752 end
2753 end
2754
2755 for _, Page in (Win.Pages or {}) do
2756 if Page.Gradient then PaintGrad(Page.Gradient) end
2757 if Page.Indicator then
2758 pcall(function() Page.Indicator.BackgroundColor3 = RGB(255, 255, 255) end)
2759 end
2760 if Page.IndicatorGlow then
2761 pcall(function()
2762 if Page.IndicatorGlow:IsA("Frame") then
2763 Page.IndicatorGlow.BackgroundColor3 = T.Accent
2764 elseif Page.IndicatorGlow:IsA("ImageLabel") then
2765 Page.IndicatorGlow.ImageColor3 = T.Accent
2766 end
2767 end)
2768 end
2769 if Page.IndicatorBloom then
2770 pcall(function() Page.IndicatorBloom.ImageColor3 = T.Accent end)
2771 end
2772 if Page.IconLabel then
2773 if Page.Opened then
2774 Page.IconLabel.ImageTransparency = 0
2775 Page.IconLabel.ImageColor3 = RGB(255, 255, 255)
2776 else
2777 Page.IconLabel.ImageTransparency = 0.5
2778 Page.IconLabel.ImageColor3 = RGB(255, 255, 255)
2779 end
2780 end
2781 for _, Sub in (Page.SubPages or {}) do
2782 local Btn = Sub.Button
2783 if Btn then
2784 local Grad = Btn:FindFirstChildOfClass("UIGradient")
2785 PaintGrad(Grad)
2786 if not (Page.ActiveSubPage == Sub) then
2787 Btn.BackgroundColor3 = T.Background
2788 end
2789 end
2790 end
2791 end
2792 end
2793
2794 -- Sections / elements walk
2795 for _, Section in (Library.Sections or {}) do
2796 local Frame = Section.Frame
2797 if Frame and Frame.Parent then
2798 pcall(function() Frame.BackgroundColor3 = T.Surface end)
2799 local St = Frame:FindFirstChildOfClass("UIStroke")
2800 if St then pcall(function() St.Color = T.SectionBorder or T.Border end) end
2801 end
2802 end
2803
2804 if Library.Watermark and Library.Watermark.Frame then
2805 Library.Watermark.Frame.BackgroundColor3 = T.Surface
2806 local Stroke = Library.Watermark.Frame:FindFirstChildOfClass("UIStroke")
2807 if Stroke then Stroke.Color = T.Border end
2808 if Library.Watermark.Accent then
2809 Library.Watermark.Accent.BackgroundColor3 = T.Accent
2810 PaintGrad(Library.Watermark.Accent:FindFirstChildOfClass("UIGradient"))
2811 end
2812 if Library.Watermark.Label then
2813 Library.Watermark.Label.TextColor3 = T.Text
2814 end
2815 end
2816 if Library.KeybindList and Library.KeybindList.Frame then
2817 Library.KeybindList.Frame.BackgroundColor3 = T.Surface
2818 local Stroke = Library.KeybindList.Frame:FindFirstChildOfClass("UIStroke")
2819 if Stroke then Stroke.Color = T.Border end
2820 if Library.KeybindList.Accent then
2821 Library.KeybindList.Accent.BackgroundColor3 = T.Accent
2822 PaintGrad(Library.KeybindList.Accent:FindFirstChildOfClass("UIGradient"))
2823 end
2824 local Header = Library.KeybindList.Frame:FindFirstChild("Header")
2825 if Header then Header.BackgroundColor3 = T.SurfaceAlt end
2826 end
2827end
2828
2829Library.Folder = "Noctro"
2830Library.ConfigExtension = ".json"
2831Library.Autoload = nil
2832Library.MenuKey = EKC.LeftAlt
2833Library.MenuOpen = true
2834Library.Windows = {}
2835Library.Auth = {
2836 Enabled = false;
2837 Validated = true;
2838 Token = nil;
2839 ExpiresAt = nil;
2840 ShowExpiry = false;
2841 WatermarkExpiry = false;
2842 Options = nil;
2843}
2844
2845local function HasFS(): boolean
2846 return typeof(writefile) == "function" and typeof(readfile) == "function"
2847end
2848
2849local function EnsureFolder()
2850 if typeof(isfolder) == "function" and typeof(makefolder) == "function" then
2851 if not isfolder(Library.Folder) then
2852 pcall(makefolder, Library.Folder)
2853 end
2854 end
2855end
2856
2857Library.SetConfigFolder = function(Path: string)
2858 if type(Path) ~= "string" or Path == "" then
2859 return Library.Folder
2860 end
2861 Path = Path:gsub("^/+", ""):gsub("/+$", ""):gsub("%.%.", "")
2862 if Path == "" then
2863 Path = "Noctro"
2864 end
2865 Library.Folder = Path
2866 EnsureFolder()
2867 return Library.Folder
2868end
2869
2870local function ConfigPath(Name: string): string
2871 return Library.Folder .. "/" .. Name .. Library.ConfigExtension
2872end
2873
2874local function EncodeColor(Color: Color3): { number }
2875 return { MR(Color.R * 255), MR(Color.G * 255), MR(Color.B * 255) }
2876end
2877
2878local function DecodeColor(Value: any): Color3?
2879 if typeof(Value) == "Color3" then
2880 return Value
2881 end
2882 if type(Value) == "table" and #Value >= 3 then
2883 return RGB(Value[1], Value[2], Value[3])
2884 end
2885 return nil
2886end
2887
2888
2889Library.GetLayout = function()
2890 local Layout = {
2891 Tabs = {};
2892 Sections = {};
2893 KeybindList = nil;
2894 Watermark = nil;
2895 }
2896 for _, Win in Library.Windows do
2897 for _, Page in (Win.Pages or {}) do
2898 local Id = tostring(Page.Icon or "") .. ":" .. tostring(Page.Button and Page.Button.LayoutOrder or 0)
2899 if Page.Button then
2900 TIS(Layout.Tabs, {
2901 Icon = Page.Icon;
2902 Order = Page.Button.LayoutOrder;
2903 })
2904 end
2905 for _, Sub in (Page.SubPages or {}) do
2906 -- sections live under subpages via Library.Sections
2907 end
2908 end
2909 end
2910 for _, Section in (Library.Sections or {}) do
2911 if Section.Frame then
2912 TIS(Layout.Sections, {
2913 Name = Section.Name;
2914 Side = Section.Side;
2915 Order = Section.Frame.LayoutOrder;
2916 })
2917 end
2918 end
2919 if Library.KeybindList and Library.KeybindList.Frame then
2920 local P = Library.KeybindList.Frame.Position
2921 Layout.KeybindList = { X = P.X.Offset; Y = P.Y.Offset }
2922 end
2923 if Library.Watermark and Library.Watermark.Frame then
2924 local P = Library.Watermark.Frame.Position
2925 Layout.Watermark = { X = P.X.Offset; Y = P.Y.Offset }
2926 end
2927 return Layout
2928end
2929
2930Library.SaveLayout = function()
2931 -- persisted via next config save; also write layout.json if FS available
2932 if not HasFS or not HasFS() then
2933 return
2934 end
2935 EnsureFolder()
2936 local Ok, Enc = pcall(function()
2937 return game:GetService("HttpService"):JSONEncode(Library.GetLayout())
2938 end)
2939 if Ok and Enc and writefile then
2940 pcall(writefile, Library.Folder .. "/layout.json", Enc)
2941 end
2942end
2943
2944Library.ApplyLayout = function(Layout)
2945 if type(Layout) ~= "table" then return end
2946 if type(Layout.Tabs) == "table" then
2947 for _, Win in Library.Windows do
2948 for _, Entry in Layout.Tabs do
2949 for _, Page in (Win.Pages or {}) do
2950 if Page.Icon == Entry.Icon and Page.Button and type(Entry.Order) == "number" then
2951 Page.Button.LayoutOrder = Entry.Order
2952 Page.LayoutOrder = Entry.Order
2953 end
2954 end
2955 end
2956 end
2957 end
2958 if type(Layout.Sections) == "table" then
2959 for _, Entry in Layout.Sections do
2960 for _, Section in (Library.Sections or {}) do
2961 if Section.Name == Entry.Name and Section.Frame then
2962 if Entry.Order then Section.Frame.LayoutOrder = Entry.Order end
2963 if Entry.Side and Section.Side ~= Entry.Side then
2964 -- move column if possible
2965 local Frame = Section.Frame
2966 local Parent = Frame.Parent and Frame.Parent.Parent
2967 if Parent then
2968 local Col = Parent:FindFirstChild(Entry.Side)
2969 if Col then
2970 Frame.Parent = Col
2971 Section.Side = Entry.Side
2972 end
2973 end
2974 end
2975 end
2976 end
2977 end
2978 end
2979 if Layout.KeybindList and Library.KeybindList and Library.KeybindList.Frame then
2980 local X, Y = Layout.KeybindList.X, Layout.KeybindList.Y
2981 if type(X) == "number" and type(Y) == "number" then
2982 Library.KeybindList.Frame.Position = ClampToScreen(Library.KeybindList.Frame, UFO(X, Y))
2983 end
2984 end
2985 if Layout.Watermark and Library.Watermark and Library.Watermark.Frame then
2986 local X, Y = Layout.Watermark.X, Layout.Watermark.Y
2987 if type(X) == "number" and type(Y) == "number" then
2988 Library.Watermark.Frame.Position = ClampToScreen(Library.Watermark.Frame, UFO(X, Y))
2989 end
2990 end
2991end
2992
2993Library.GetConfig = function()
2994 local Data = {
2995 Flags = {};
2996 Theme = {};
2997 Layout = Library.GetLayout and Library.GetLayout() or {};
2998 MenuKey = Library.MenuKey and Library.MenuKey.Name or "LeftAlt";
2999 }
3000
3001 for Flag, Entry in Library.Flags do
3002 local Value = Entry.Value
3003 if typeof(Value) == "Color3" then
3004 Data.Flags[Flag] = {
3005 Type = "Color3";
3006 Color = EncodeColor(Value);
3007 Transparency = Entry.Transparency or 0;
3008 }
3009 elseif typeof(Value) == "EnumItem" then
3010 Data.Flags[Flag] = { Type = "Enum"; EnumType = tostring(Value.EnumType); Name = Value.Name }
3011 elseif type(Value) == "table" then
3012 Data.Flags[Flag] = { Type = "table"; Value = Value }
3013 else
3014 Data.Flags[Flag] = { Type = type(Value); Value = Value }
3015 end
3016 end
3017
3018 for Key, Color in Library.Theme do
3019 if typeof(Color) == "Color3" then
3020 Data.Theme[Key] = EncodeColor(Color)
3021 end
3022 end
3023
3024 if Library.KeybindList and Library.KeybindList.Frame then
3025 local P = Library.KeybindList.Frame.Position
3026 Data.KeybindListPos = { X = P.X.Offset; Y = P.Y.Offset }
3027 elseif Library.KeybindList and Library.KeybindList.SavedPos then
3028 Data.KeybindListPos = Library.KeybindList.SavedPos
3029 end
3030
3031 return Data
3032end
3033
3034Library.SetFlag = function(Flag: string, Value: any, Transparency: number?)
3035 local Entry = Library.Flags[Flag]
3036 if not Entry then
3037 return
3038 end
3039 if Entry.Set then
3040 if Transparency ~= nil then
3041 Entry.Set(Value, Transparency)
3042 elseif type(Value) == "boolean" then
3043
3044 Entry.Set(Value, true)
3045 else
3046 Entry.Set(Value)
3047 end
3048 else
3049 Entry.Value = Value
3050 end
3051end
3052
3053Library.LoadConfigData = function(Data: {})
3054 if type(Data) ~= "table" then
3055 return
3056 end
3057
3058 if type(Data.Theme) == "table" then
3059 for Key, Value in Data.Theme do
3060 local Color = DecodeColor(Value)
3061 if Color then
3062 Library.Theme[Key] = Color
3063 end
3064 end
3065 end
3066
3067 if type(Data.KeybindListPos) == "table" then
3068 Library.KeybindList = Library.KeybindList or {}
3069 Library.KeybindList.SavedPos = {
3070 X = tonumber(Data.KeybindListPos.X) or 18;
3071 Y = tonumber(Data.KeybindListPos.Y) or 200;
3072 }
3073 if Library.KeybindList.Frame then
3074 local Pos = UFO(Library.KeybindList.SavedPos.X, Library.KeybindList.SavedPos.Y)
3075 Library.KeybindList.Frame.Position = ClampToScreen(Library.KeybindList.Frame, Pos)
3076 end
3077 end
3078
3079 if type(Data.MenuKey) == "string" and EKC[Data.MenuKey] then
3080 Library.MenuKey = EKC[Data.MenuKey]
3081 end
3082
3083 if type(Data.Flags) == "table" then
3084 for Flag, Packed in Data.Flags do
3085 local Entry = Library.Flags[Flag]
3086 if Entry and type(Packed) == "table" then
3087 local Type = Packed.Type
3088 if Type == "Color3" then
3089 local Color = DecodeColor(Packed.Color)
3090 if Color then
3091 Library.SetFlag(Flag, Color, Packed.Transparency)
3092 end
3093 elseif Type == "Enum" and Packed.Name then
3094 local EnumRoot = Enum
3095 local EnumType = EnumRoot[Packed.EnumType]
3096 if EnumType and EnumType[Packed.Name] then
3097 Library.SetFlag(Flag, EnumType[Packed.Name])
3098 end
3099 elseif Type == "table" then
3100 Library.SetFlag(Flag, Packed.Value)
3101 else
3102 Library.SetFlag(Flag, Packed.Value)
3103 end
3104 end
3105 end
3106 end
3107end
3108
3109Library.SaveConfig = function(Name: string)
3110 if not HasFS() then
3111 warn("[Noctro] writefile/readfile unavailable in this environment")
3112 return false
3113 end
3114 EnsureFolder()
3115 Name = tostring(Name or "default"):gsub("[^%w%-%_ ]", "")
3116 if Name == "" then Name = "default" end
3117 local Data = Library.GetConfig()
3118 Data.Name = Name
3119 Data.SavedAt = os.date("%Y-%m-%d %H:%M:%S")
3120 local Ok, Encoded = pcall(function()
3121 return game:GetService("HttpService"):JSONEncode(Data)
3122 end)
3123 if not Ok then
3124 warn("[Noctro] failed to encode config", Encoded)
3125 return false
3126 end
3127 local Path = ConfigPath(Name)
3128 local WOk, WErr = pcall(writefile, Path, Encoded)
3129 if not WOk then
3130 warn("[Noctro] writefile failed", WErr)
3131 return false
3132 end
3133 return true
3134end
3135
3136Library.LoadConfig = function(Name: string)
3137 if not HasFS() then
3138 warn("[Noctro] writefile/readfile unavailable in this environment")
3139 return false
3140 end
3141 Name = tostring(Name or "default")
3142 local Path = ConfigPath(Name)
3143 local Exists = true
3144 if typeof(isfile) == "function" then
3145 Exists = isfile(Path)
3146 end
3147 if not Exists then
3148 warn("[Noctro] config not found:", Name)
3149 return false
3150 end
3151 local ROk, Raw = pcall(readfile, Path)
3152 if not ROk then
3153 warn("[Noctro] readfile failed", Raw)
3154 return false
3155 end
3156 local Ok, Data = pcall(function()
3157 return game:GetService("HttpService"):JSONDecode(Raw)
3158 end)
3159 if not Ok or type(Data) ~= "table" then
3160 warn("[Noctro] invalid config:", Name)
3161 return false
3162 end
3163 Library.LoadConfigData(Data)
3164 if Library.ApplyTheme then
3165 Library.ApplyTheme()
3166 end
3167 if Library.SyncThemePickers then
3168 Library.SyncThemePickers()
3169 end
3170 return true
3171end
3172
3173Library.DeleteConfig = function(Name: string)
3174 if not delfile or not isfile then
3175 return false
3176 end
3177 local Path = ConfigPath(Name)
3178 if isfile(Path) then
3179 delfile(Path)
3180 return true
3181 end
3182 return false
3183end
3184
3185Library.ListConfigs = function(): { string }
3186 local List = {}
3187 if not listfiles then
3188 return List
3189 end
3190 EnsureFolder()
3191 local Ok, Files = pcall(listfiles, Library.Folder)
3192 if not Ok or type(Files) ~= "table" then
3193 return List
3194 end
3195 for _, Path in Files do
3196 local Name = tostring(Path):match("([^/\\]+)%.json$")
3197 if Name then
3198 TIS(List, Name)
3199 end
3200 end
3201 table.sort(List)
3202 return List
3203end
3204
3205Library.SetAutoload = function(Name: string?)
3206 Library.Autoload = Name
3207 if writefile then
3208 EnsureFolder()
3209 writefile(Library.Folder .. "/autoload.txt", Name or "")
3210 end
3211end
3212
3213Library.GetAutoload = function(): string?
3214 if Library.Autoload then
3215 return Library.Autoload
3216 end
3217 if isfile and isfile(Library.Folder .. "/autoload.txt") then
3218 local Name = readfile(Library.Folder .. "/autoload.txt")
3219 if Name ~= "" then
3220 Library.Autoload = Name
3221 return Name
3222 end
3223 end
3224 return nil
3225end
3226
3227Library.RegisterFlag = function(Flag: string, Entry: {})
3228 if not Flag or Flag == "" then
3229 return
3230 end
3231 Library.Flags[Flag] = Entry
3232end
3233
3234Library.LoadingScreen = function(self: Library, propertyTable: {})
3235 local Props = Overwrite({
3236 Title = "Noctro";
3237 Subtitle = "Loading…";
3238 Duration = 1.6;
3239 }, propertyTable or {})
3240
3241 local Gui = Add("ScreenGui", {
3242 Parent = RunService:IsStudio() and Client.PlayerGui or Services:GetService("CoreGui");
3243 Name = "NoctroLoading";
3244 ZIndexBehavior = ZIB.Sibling;
3245 IgnoreGuiInset = true;
3246 })
3247
3248 local Card = Add("Frame", {
3249 Parent = Gui;
3250 AnchorPoint = V2(0.5, 0.5);
3251 Position = UFS(0.5, 0.5);
3252 Size = UFO(280, 120);
3253 BackgroundColor3 = Library.Theme.Surface;
3254 BorderSizePixel = 0;
3255 ZIndex = 50;
3256 })
3257 Add("UIShadow", { Parent = Card; BlurRadius = UD(0, 24); Spread = UFO(6, 6); Transparency = 0.55; })
3258 Add("UICorner", { Parent = Card; CornerRadius = UD(0, 8); })
3259 Add("UIStroke", { Parent = Card; ApplyStrokeMode = ASM.Border; Color = Library.Theme.Border; })
3260 Add("TextLabel", {
3261 Parent = Card;
3262 BackgroundTransparency = 1;
3263 Position = UFO(0, 28);
3264 Size = UD2(1, 0, 0, 22);
3265 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3266 Text = Props.Title;
3267 TextColor3 = Library.Theme.Text;
3268 TextSize = 18;
3269 })
3270 Add("TextLabel", {
3271 Parent = Card;
3272 BackgroundTransparency = 1;
3273 Position = UFO(0, 54);
3274 Size = UD2(1, 0, 0, 18);
3275 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3276 Text = Props.Subtitle;
3277 TextColor3 = Library.Theme.Text;
3278 TextTransparency = 0.45;
3279 TextSize = 13;
3280 })
3281 local BarBG = Add("Frame", {
3282 Parent = Card;
3283 BackgroundColor3 = Library.Theme.SurfaceAlt;
3284 BorderSizePixel = 0;
3285 Position = UD2(0.5, 0, 1, -28);
3286 AnchorPoint = V2(0.5, 0);
3287 Size = UD2(0.7, 0, 0, 6);
3288 })
3289 Add("UICorner", { Parent = BarBG; CornerRadius = UD(1, 0); })
3290 local Bar = Add("Frame", {
3291 Parent = BarBG;
3292 BackgroundColor3 = Library.Theme.Accent;
3293 BorderSizePixel = 0;
3294 Size = UD2(0, 0, 1, 0);
3295 })
3296 Add("UICorner", { Parent = Bar; CornerRadius = UD(1, 0); })
3297 Add("UIGradient", {
3298 Parent = Bar;
3299 Color = CS{ CSK(0, Library.Theme.AccentDark), CSK(1, Library.Theme.Accent) };
3300 Rotation = -90;
3301 })
3302
3303 Tween(Bar, { Size = UD2(1, 0, 1, 0) }, Props.Duration, ES.Quad, ED.Out)
3304
3305 local Done = Instance.new("BindableEvent")
3306 task.delay(Props.Duration + 0.15, function()
3307 Tween(Card, { BackgroundTransparency = 1 }, 0.3)
3308 for _, D in Card:GetDescendants() do
3309 if D:IsA("TextLabel") then
3310 Tween(D, { TextTransparency = 1 }, 0.25)
3311 elseif D:IsA("Frame") and D ~= Card then
3312 Tween(D, { BackgroundTransparency = 1 }, 0.25)
3313 end
3314 end
3315 task.wait(0.35)
3316 Gui:Destroy()
3317 Done:Fire()
3318 end)
3319
3320 Done.Event:Wait()
3321 Done:Destroy()
3322 return Gui
3323end
3324
3325Library.UIScale = 1
3326
3327Library.SetScale = function(Scale: number)
3328 Scale = MC(Scale / (Scale > 2 and 100 or 1), 0.75, 1.25)
3329 Library.UIScale = Scale
3330 for _, Win in Library.Windows do
3331 if Win.Canvas then
3332 local Existing = Win.Canvas:FindFirstChildOfClass("UIScale")
3333 if not Existing then
3334 Existing = Add("UIScale", { Parent = Win.Canvas })
3335 end
3336
3337 local Abs = Win.Canvas.AbsolutePosition
3338 local Size = Win.Canvas.AbsoluteSize
3339 local Center = Abs + Size * 0.5
3340 Existing.Scale = Scale
3341 task.defer(function()
3342 if not Win.Canvas or not Win.Canvas.Parent then return end
3343 local NewSize = Win.Canvas.AbsoluteSize
3344 local NewPos = Center - NewSize * 0.5
3345 Win.Canvas.Position = ClampToScreen(Win.Canvas, UFO(NewPos.X, NewPos.Y))
3346 end)
3347 end
3348 end
3349end
3350
3351Library.Watermark = {
3352 Enabled = true;
3353 Text = "Noctro";
3354 Frame = nil :: Frame?;
3355}
3356
3357Library.KeybindList = {
3358 Enabled = true;
3359 Frame = nil :: Frame?;
3360 Rows = {} :: { [string]: Frame };
3361}
3362
3363local function EnsureOverlayGui()
3364 if Library._Overlay then
3365 return Library._Overlay
3366 end
3367 Library._Overlay = Add("ScreenGui", {
3368 Parent = RunService:IsStudio() and Client.PlayerGui or Services:GetService("CoreGui");
3369 Name = "NoctroOverlay";
3370 ZIndexBehavior = ZIB.Sibling;
3371 IgnoreGuiInset = true;
3372 })
3373 return Library._Overlay
3374end
3375
3376Library.NotifyPosition = "Top Right"
3377Library.Notifications = {}
3378
3379Library.SetWatermark = function(Text: string?, Enabled: boolean?)
3380 if Enabled ~= nil then
3381 Library.Watermark.Enabled = Enabled
3382 end
3383 if Text ~= nil then
3384 Library.Watermark.Text = Text
3385 end
3386
3387 local Gui = EnsureOverlayGui()
3388 if Library.Watermark.Frame then
3389 Library.Watermark.Frame:Destroy()
3390 Library.Watermark.Frame = nil
3391 end
3392
3393 local Frame = Add("Frame", {
3394 Parent = Gui;
3395 Name = "Watermark";
3396 AnchorPoint = V2(0.5, 0);
3397 Position = UD2(0.5, 0, 0, 12);
3398 AutomaticSize = AS.X;
3399 Size = UFO(0, 32);
3400 BackgroundColor3 = Library.Theme.Surface;
3401 BorderSizePixel = 0;
3402 ZIndex = 120;
3403 Visible = Library.Watermark.Enabled == true;
3404 })
3405 Add("UICorner", { Parent = Frame; CornerRadius = UD(0, 7); })
3406 Add("UIStroke", { Parent = Frame; ApplyStrokeMode = ASM.Border; Color = Library.Theme.Border; })
3407 Add("UIShadow", { Parent = Frame; BlurRadius = UD(0, 16); Spread = UFO(4, 4); Transparency = 0.7; })
3408 Add("UIPadding", { Parent = Frame; PaddingLeft = UD(0, 10); PaddingRight = UD(0, 12); })
3409 Add("UIListLayout", {
3410 Parent = Frame;
3411 FillDirection = FD.Horizontal;
3412 Padding = UD(0, 8);
3413 VerticalAlignment = VFA.Center;
3414 SortOrder = SO.LayoutOrder;
3415 })
3416
3417 local Logo = Add("Frame", {
3418 Parent = Frame;
3419 BackgroundColor3 = Library.Theme.Accent;
3420 BorderSizePixel = 0;
3421 Size = UFO(16, 16);
3422 LayoutOrder = 0;
3423 })
3424 Add("UICorner", { Parent = Logo; CornerRadius = UD(0, 4); })
3425 Add("UIGradient", {
3426 Parent = Logo;
3427 Color = CS{ CSK(0, Library.Theme.AccentDark), CSK(1, Library.Theme.Accent) };
3428 Rotation = -45;
3429 })
3430
3431 local function Chip(Text: string, Order: number, Dim: boolean?): TextLabel
3432 return Add("TextLabel", {
3433 Parent = Frame;
3434 BackgroundTransparency = 1;
3435 AutomaticSize = AS.X;
3436 Size = UFO(0, 32);
3437 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3438 Text = Text;
3439 TextColor3 = Dim and RGB(150, 154, 170) or RGB(235, 236, 240);
3440 TextSize = 12;
3441 LayoutOrder = Order;
3442 })
3443 end
3444
3445 local function Sep(Order: number)
3446 return Chip("-", Order, true)
3447 end
3448
3449 local CleanText = tostring(Library.Watermark.Text or "Noctro")
3450
3451 local Built = {}
3452 for i = 1, #CleanText do
3453 local c = CleanText:sub(i, i)
3454 local b = string.byte(c)
3455 if (b >= 48 and b <= 57) or (b >= 65 and b <= 90) or (b >= 97 and b <= 122) or c == " " or c == "-" or c == "_" then
3456 table.insert(Built, c)
3457 else
3458 table.insert(Built, " ")
3459 end
3460 end
3461 CleanText = table.concat(Built)
3462 CleanText = CleanText:gsub("%s+", " ")
3463 CleanText = CleanText:gsub("^%s+", ""):gsub("%s+$", "")
3464 if CleanText == "" then
3465 CleanText = "Noctro"
3466 end
3467
3468 if CleanText:match("^%d+$") then
3469 CleanText = "Noctro"
3470 end
3471
3472 local Title = Chip(CleanText, 1, false)
3473 local Order = 2
3474 if Library.Auth and Library.Auth.Validated and Library.Auth.WatermarkExpiry and Library.Auth.ExpiresAt and Library.FormatExpiry then
3475 Sep(Order)
3476 Order = Order + 1
3477 Chip(Library.FormatExpiry(Library.Auth.ExpiresAt), Order, true)
3478 Order = Order + 1
3479 end
3480 Sep(Order)
3481 Order = Order + 1
3482 local FpsL = Chip("0 fps", Order, true)
3483 Order = Order + 1
3484 Sep(Order)
3485 Order = Order + 1
3486 local PingL = Chip("0 ms", Order, true)
3487 Order = Order + 1
3488 Sep(Order)
3489 Order = Order + 1
3490 local TimeL = Chip(os.date("%H:%M:%S"), Order, true)
3491
3492 Library.Watermark.Frame = Frame
3493 Library.Watermark.Label = Title
3494 Library.Watermark.Stats = FpsL
3495 Library.Watermark.Accent = Logo
3496
3497 if Library.Watermark._StatsConn then
3498 Library.Watermark._StatsConn:Disconnect()
3499 end
3500 local Frames, Last = 0, os.clock()
3501 Library.Watermark._StatsConn = RunService.RenderStepped:Connect(function()
3502 if not Library.Watermark.Enabled or not Frame.Parent then
3503 return
3504 end
3505 Frames = Frames + 1
3506 local Now = os.clock()
3507 if Now - Last >= 1 then
3508 FpsL.Text = string.format("%d fps", Frames)
3509 local Ping = 0
3510 pcall(function()
3511 Ping = math.floor(game:GetService("Stats").Network.ServerStatsItem["Data Ping"]:GetValue())
3512 end)
3513 PingL.Text = string.format("%d ms", Ping)
3514 TimeL.Text = os.date("%H:%M:%S")
3515 Frames = 0
3516 Last = Now
3517 end
3518 end)
3519end
3520
3521Library.SetKeybindList = function(Enabled: boolean?)
3522 if Enabled ~= nil then
3523 Library.KeybindList.Enabled = Enabled
3524 end
3525
3526 local Gui = EnsureOverlayGui()
3527 if Library.KeybindList.Frame then
3528 Library.KeybindList.Frame:Destroy()
3529 Library.KeybindList.Frame = nil
3530 Library.KeybindList.Rows = {}
3531 end
3532
3533 local T = Library.Theme
3534 local Panel = Add("Frame", {
3535 Parent = Gui;
3536 Name = "KeybindList";
3537 Position = UFO(18, math.floor((workspace.CurrentCamera and workspace.CurrentCamera.ViewportSize.Y or 800) * 0.35));
3538 Size = UFO(280, 0);
3539 AutomaticSize = AS.Y;
3540 BackgroundColor3 = T.Surface;
3541 BorderSizePixel = 0;
3542 Visible = Library.KeybindList.Enabled == true;
3543 ZIndex = 120;
3544 Active = true;
3545 })
3546 Add("UICorner", { Parent = Panel; CornerRadius = UD(0, 10); })
3547 Add("UIStroke", { Parent = Panel; ApplyStrokeMode = ASM.Border; Color = RGB(30, 30, 36); })
3548 Add("UIPadding", {
3549 Parent = Panel;
3550 PaddingTop = UD(0, 12);
3551 PaddingBottom = UD(0, 10);
3552 PaddingLeft = UD(0, 12);
3553 PaddingRight = UD(0, 12);
3554 })
3555 Add("UIListLayout", {
3556 Parent = Panel;
3557 SortOrder = SO.LayoutOrder;
3558 Padding = UD(0, 10);
3559 })
3560
3561 local Header = Add("TextButton", {
3562 Parent = Panel;
3563 Name = "Header";
3564 Size = UD2(1, 0, 0, 22);
3565 BackgroundTransparency = 1;
3566 Text = "";
3567 AutoButtonColor = false;
3568 LayoutOrder = 0;
3569 ZIndex = 121;
3570 })
3571 local HeaderIcon = Add("Frame", {
3572 Parent = Header;
3573 BackgroundColor3 = T.Accent;
3574 Size = UFO(8, 8);
3575 Position = UFO(0, 7);
3576 BorderSizePixel = 0;
3577 })
3578 Add("UICorner", { Parent = HeaderIcon; CornerRadius = UD(1, 0); })
3579 Add("UIGradient", {
3580 Parent = HeaderIcon;
3581 Color = CS{ CSK(0, T.AccentDark), CSK(1, T.Accent) };
3582 Rotation = -90;
3583 })
3584 Add("TextLabel", {
3585 Parent = Header;
3586 BackgroundTransparency = 1;
3587 Position = UFO(16, 0);
3588 Size = UD2(1, -16, 1, 0);
3589 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3590 Text = "Keybind list";
3591 TextColor3 = T.Text;
3592 TextSize = 14;
3593 TextXAlignment = TXA.Left;
3594 })
3595
3596 local Body = Add("Frame", {
3597 Parent = Panel;
3598 Name = "Body";
3599 BackgroundTransparency = 1;
3600 Size = UD2(1, 0, 0, 0);
3601 AutomaticSize = AS.Y;
3602 LayoutOrder = 1;
3603 ClipsDescendants = true;
3604 })
3605 Add("UIListLayout", { Parent = Body; SortOrder = SO.LayoutOrder; Padding = UD(0, 8); })
3606
3607 local Cols = Add("Frame", {
3608 Parent = Body;
3609 Name = "Cols";
3610 BackgroundTransparency = 1;
3611 Size = UD2(1, 0, 0, 16);
3612 LayoutOrder = 1;
3613 })
3614 local function Col(Text: string, Pos: UDim2, Size: UDim2, Align: Enum.TextXAlignment)
3615 Add("TextLabel", {
3616 Parent = Cols;
3617 BackgroundTransparency = 1;
3618 Position = Pos;
3619 Size = Size;
3620 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3621 Text = Text;
3622 TextColor3 = RGB(160, 160, 165);
3623 TextSize = 12;
3624 TextXAlignment = Align;
3625 })
3626 end
3627 Col("Function", UFO(6, 0), UFO(118, 16), TXA.Left)
3628 Col("Hotkey", UFO(128, 0), UFO(72, 16), TXA.Center)
3629 Col("Status", UFO(200, 0), UFO(56, 16), TXA.Right)
3630
3631 Add("Frame", {
3632 Parent = Body;
3633 Name = "Divider";
3634 Size = UD2(1, 0, 0, 1);
3635 BackgroundColor3 = RGB(21, 21, 23);
3636 BorderSizePixel = 0;
3637 LayoutOrder = 2;
3638 })
3639
3640 local Rows = Add("Frame", {
3641 Parent = Body;
3642 Name = "Rows";
3643 BackgroundTransparency = 1;
3644 Size = UD2(1, 0, 0, 0);
3645 AutomaticSize = AS.Y;
3646 LayoutOrder = 3;
3647 })
3648 Add("UIListLayout", { Parent = Rows; SortOrder = SO.LayoutOrder; Padding = UD(0, 2); })
3649
3650 BindDrag(Panel, Header, true)
3651 Panel:GetPropertyChangedSignal("Position"):Connect(function()
3652 local P = Panel.Position
3653 Library.KeybindList.SavedPos = { X = P.X.Offset; Y = P.Y.Offset }
3654 end)
3655 task.defer(function()
3656 if not (Panel and Panel.Parent) then return end
3657 if Library.KeybindList.SavedPos then
3658 Panel.Position = ClampToScreen(Panel, UFO(Library.KeybindList.SavedPos.X, Library.KeybindList.SavedPos.Y))
3659 else
3660 Panel.Position = ClampToScreen(Panel, Panel.Position)
3661 end
3662 end)
3663
3664 Library.KeybindList.Frame = Panel
3665 Library.KeybindList.Body = Body
3666 Library.KeybindList.RowsFolder = Rows
3667 Library.KeybindList.Rows = {}
3668 Library.KeybindList.Accent = HeaderIcon
3669
3670 for _, Entry in pairs(Library.KeybindRegistry or {}) do
3671 Library.UpdateKeybindList(Entry.Name, Entry.KeyText, Entry.Active, Entry.Mode)
3672 end
3673end
3674
3675Library.UpdateKeybindList = function(Name: string, KeyText: string, Active: boolean?, Mode: string?)
3676 if not Library.KeybindList.Enabled then
3677 return
3678 end
3679 if not Library.KeybindList.Frame or not Library.KeybindList.RowsFolder then
3680 Library.SetKeybindList(true)
3681 end
3682
3683 Mode = Mode or "Toggle"
3684 KeyText = KeyText or "—"
3685 local Rows = Library.KeybindList.Rows
3686 local Folder = Library.KeybindList.RowsFolder
3687 local T = Library.Theme
3688 local Row = Rows[Name]
3689
3690 if not Row then
3691 local Frame = Add("TextButton", {
3692 Parent = Folder;
3693 Text = "";
3694 AutoButtonColor = false;
3695 BackgroundColor3 = RGB(25, 25, 29);
3696 BackgroundTransparency = 1;
3697 Size = UD2(1, 0, 0, 26);
3698 BorderSizePixel = 0;
3699 ZIndex = 122;
3700 })
3701 Add("UICorner", { Parent = Frame; CornerRadius = UD(0, 6); })
3702
3703 local NameLbl = Add("TextLabel", {
3704 Parent = Frame;
3705 Name = "Name";
3706 BackgroundTransparency = 1;
3707 Position = UFO(6, 0);
3708 Size = UFO(118, 26);
3709 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3710 Text = Name;
3711 TextColor3 = T.Text;
3712 TextSize = 12;
3713 TextXAlignment = TXA.Left;
3714 TextTruncate = ETT.AtEnd;
3715 })
3716 local KeyLbl = Add("TextLabel", {
3717 Parent = Frame;
3718 Name = "Key";
3719 BackgroundTransparency = 1;
3720 Position = UFO(128, 0);
3721 Size = UFO(72, 26);
3722 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3723 Text = KeyText;
3724 TextColor3 = T.Text;
3725 TextSize = 12;
3726 TextXAlignment = TXA.Center;
3727 TextTruncate = ETT.AtEnd;
3728 })
3729 local StatusLbl = Add("TextLabel", {
3730 Parent = Frame;
3731 Name = "Status";
3732 BackgroundTransparency = 1;
3733 Position = UFO(200, 0);
3734 Size = UFO(56, 26);
3735 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3736 Text = Mode;
3737 TextColor3 = RGB(160, 160, 165);
3738 TextSize = 12;
3739 TextXAlignment = TXA.Right;
3740 })
3741
3742 Frame.MouseEnter:Connect(function()
3743 if Frame:GetAttribute("Active") then return end
3744 Tween(Frame, { BackgroundTransparency = 0.55 }, 0.12)
3745 end)
3746 Frame.MouseLeave:Connect(function()
3747 if Frame:GetAttribute("Active") then
3748 Tween(Frame, { BackgroundTransparency = 0 }, 0.12)
3749 else
3750 Tween(Frame, { BackgroundTransparency = 1 }, 0.12)
3751 end
3752 end)
3753
3754 Row = { Frame = Frame; Name = NameLbl; Key = KeyLbl; Status = StatusLbl }
3755 Rows[Name] = Row
3756 end
3757
3758 Row.Key.Text = KeyText
3759 Row.Status.Text = Mode
3760 Row.Frame:SetAttribute("Active", Active == true)
3761
3762 if Active then
3763 Tween(Row.Frame, { BackgroundTransparency = 0 }, 0.12)
3764 Row.Name.TextColor3 = T.Text
3765 Row.Key.TextColor3 = T.Accent
3766 Row.Status.TextColor3 = T.Accent
3767 else
3768 Tween(Row.Frame, { BackgroundTransparency = 1 }, 0.12)
3769 Row.Name.TextColor3 = T.Text
3770 Row.Key.TextColor3 = T.Text
3771 Row.Status.TextColor3 = RGB(160, 160, 165)
3772 end
3773end
3774
3775Library._NotifyOrder = 0
3776Library._Toasts = {}
3777Library.MaxNotifications = 4
3778Library.NotifyToggles = true
3779
3780Library.Notify = function(propertyTable: {})
3781 local Props = Overwrite({
3782 Title = "Notification";
3783 Text = "";
3784 Content = nil;
3785 Duration = 4;
3786 Type = "Info";
3787 Icon = nil;
3788 }, propertyTable or {})
3789
3790 local Content = Props.Content or Props.Text or Props.Message or ""
3791 local Duration = Props.Duration or 4
3792 local T = Library.Theme
3793
3794 local TypeColor = T.Text
3795 if Props.Type == "Success" then
3796 TypeColor = RGB(150, 220, 170)
3797 elseif Props.Type == "Warning" or Props.Type == "Warn" then
3798 TypeColor = RGB(240, 176, 108)
3799 elseif Props.Type == "Error" then
3800 TypeColor = RGB(240, 120, 120)
3801 end
3802
3803 local Gui = EnsureOverlayGui()
3804 if not Library._NotifyHost then
3805 Library._NotifyHost = Add("Frame", {
3806 Parent = Gui;
3807 Name = "Notifications";
3808 BackgroundTransparency = 1;
3809 Size = UFO(220, 0);
3810 AutomaticSize = AS.Y;
3811 ZIndex = 200;
3812 })
3813 Add("UIListLayout", {
3814 Parent = Library._NotifyHost;
3815 Padding = UD(0, 10);
3816 SortOrder = SO.LayoutOrder;
3817 HorizontalAlignment = HFA.Right;
3818 })
3819 end
3820
3821 local Pos = Library.NotifyPosition or "Top Right"
3822 local Layout = Library._NotifyHost:FindFirstChildOfClass("UIListLayout")
3823 if Pos == "Top Left" then
3824 Library._NotifyHost.AnchorPoint = V2(0, 0)
3825 Library._NotifyHost.Position = UFO(16, 16)
3826 Layout.HorizontalAlignment = HFA.Left
3827 elseif Pos == "Bottom Left" then
3828 Library._NotifyHost.AnchorPoint = V2(0, 1)
3829 Library._NotifyHost.Position = UD2(0, 16, 1, -16)
3830 Layout.HorizontalAlignment = HFA.Left
3831 elseif Pos == "Bottom Right" then
3832 Library._NotifyHost.AnchorPoint = V2(1, 1)
3833 Library._NotifyHost.Position = UD2(1, -16, 1, -16)
3834 Layout.HorizontalAlignment = HFA.Right
3835 else
3836 Library._NotifyHost.AnchorPoint = V2(1, 0)
3837 Library._NotifyHost.Position = UD2(1, -16, 0, 16)
3838 Layout.HorizontalAlignment = HFA.Right
3839 end
3840
3841 Library._NotifyOrder = (Library._NotifyOrder or 0) + 1
3842
3843 local HasBody = Content ~= ""
3844 local CardH = HasBody and 52 or 36
3845 local SlideDir = (string.find(Pos, "Left") and -1) or 1
3846
3847 local Slot = Add("Frame", {
3848 Parent = Library._NotifyHost;
3849 Size = UD2(1, 0, 0, CardH + 4);
3850 BackgroundTransparency = 1;
3851 LayoutOrder = Library._NotifyOrder;
3852 ClipsDescendants = false;
3853 })
3854
3855 local Shell = Add("Frame", {
3856 Parent = Slot;
3857 Position = UFO(280 * SlideDir, 0);
3858 Size = UD2(1, 0, 0, CardH);
3859 BackgroundTransparency = 1;
3860 })
3861
3862 local Shadow = Add("ImageLabel", {
3863 Parent = Shell;
3864 Position = UFO(-12, -12);
3865 Size = UD2(1, 24, 1, 24);
3866 BackgroundTransparency = 1;
3867 Image = "rbxassetid://6014261993";
3868 ImageColor3 = RGB(0, 0, 0);
3869 ImageTransparency = 1;
3870 ScaleType = SCL.Slice;
3871 SliceCenter = Rect.new(49, 49, 450, 450);
3872 ZIndex = 0;
3873 })
3874
3875 local Card = Add("CanvasGroup", {
3876 Parent = Shell;
3877 Size = UFS(1, 1);
3878 BackgroundColor3 = T.Background or RGB(14, 14, 16);
3879 BorderSizePixel = 0;
3880 GroupTransparency = 1;
3881 ZIndex = 1;
3882 })
3883 Add("UICorner", { Parent = Card; CornerRadius = UD(0, 8); })
3884 local CardStroke = Add("UIStroke", {
3885 Parent = Card;
3886 ApplyStrokeMode = ASM.Border;
3887 Color = T.Border or RGB(30, 30, 36);
3888 Thickness = 1;
3889 })
3890
3891 Add("Frame", {
3892 Parent = Card;
3893 Size = UD2(1, 0, 0, 1);
3894 BackgroundColor3 = RGB(255, 255, 255);
3895 BackgroundTransparency = 0.93;
3896 BorderSizePixel = 0;
3897 ZIndex = 2;
3898 })
3899
3900 local Body = Add("Frame", {
3901 Parent = Card;
3902 Size = UD2(1, 0, 1, -6);
3903 BackgroundTransparency = 1;
3904 ZIndex = 3;
3905 })
3906 Add("UIPadding", {
3907 Parent = Body;
3908 PaddingLeft = UD(0, 10);
3909 PaddingRight = UD(0, 6);
3910 PaddingTop = UD(0, 6);
3911 PaddingBottom = UD(0, 4);
3912 })
3913
3914 Add("TextLabel", {
3915 Parent = Body;
3916 BackgroundTransparency = 1;
3917 Size = UD2(1, -16, 0, 14);
3918 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3919 Text = Props.Title or "Notification";
3920 TextColor3 = TypeColor;
3921 TextSize = 12;
3922 TextXAlignment = TXA.Left;
3923 TextTruncate = ETT.AtEnd;
3924 ZIndex = 4;
3925 })
3926
3927 local Close = Add("TextButton", {
3928 Parent = Body;
3929 AnchorPoint = V2(1, 0);
3930 Position = UD2(1, 0, 0, -2);
3931 Size = UFO(16, 16);
3932 BackgroundTransparency = 1;
3933 Text = "x";
3934 TextColor3 = RGB(140, 144, 155);
3935 TextSize = 12;
3936 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3937 AutoButtonColor = false;
3938 ZIndex = 5;
3939 })
3940 Close.MouseEnter:Connect(function()
3941 Tween(Close, { TextColor3 = T.Text }, 0.12)
3942 end)
3943 Close.MouseLeave:Connect(function()
3944 Tween(Close, { TextColor3 = RGB(140, 144, 155) }, 0.15)
3945 end)
3946
3947 if HasBody then
3948 Add("TextLabel", {
3949 Parent = Body;
3950 BackgroundTransparency = 1;
3951 Position = UFO(0, 15);
3952 Size = UD2(1, -4, 0, 14);
3953 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
3954 Text = Content;
3955 TextColor3 = RGB(155, 158, 168);
3956 TextSize = 11;
3957 TextXAlignment = TXA.Left;
3958 TextTruncate = ETT.AtEnd;
3959 ZIndex = 4;
3960 })
3961 end
3962
3963 local BarBG = Add("Frame", {
3964 Parent = Card;
3965 AnchorPoint = V2(0, 1);
3966 Position = UD2(0, 10, 1, -4);
3967 Size = UD2(1, -20, 0, 2);
3968 BackgroundColor3 = T.SurfaceAlt or RGB(28, 28, 30);
3969 BorderSizePixel = 0;
3970 ZIndex = 5;
3971 })
3972 Add("UICorner", { Parent = BarBG; CornerRadius = UD(1, 0); })
3973 local Bar = Add("Frame", {
3974 Parent = BarBG;
3975 Size = UFS(1, 1);
3976 BackgroundColor3 = T.Accent;
3977 BorderSizePixel = 0;
3978 })
3979 Add("UICorner", { Parent = Bar; CornerRadius = UD(1, 0); })
3980
3981 Tween(Shell, { Position = UFO(0, 0) }, 0.35, ES.Quint)
3982 Tween(Card, { GroupTransparency = 0 }, 0.22)
3983 Tween(Shadow, { ImageTransparency = 0.7 }, 0.3)
3984 Tween(Bar, { Size = UD2(0, 0, 1, 0) }, Duration, ES.Linear)
3985
3986 local Closed = false
3987 local function Dismiss()
3988 if Closed then return end
3989 Closed = true
3990 for i, Fn in Library._Toasts do
3991 if Fn == Dismiss then
3992 table.remove(Library._Toasts, i)
3993 break
3994 end
3995 end
3996 Slot.ClipsDescendants = true
3997 Tween(Shell, { Position = UFO(280 * SlideDir, 0) }, 0.25, ES.Quint)
3998 Tween(Card, { GroupTransparency = 1 }, 0.18)
3999 Tween(CardStroke, { Transparency = 1 }, 0.12)
4000 Tween(Shadow, { ImageTransparency = 1 }, 0.18)
4001 task.delay(0.2, function()
4002 Tween(Slot, { Size = UD2(1, 0, 0, 0) }, 0.18, ES.Quint)
4003 task.delay(0.2, function()
4004 Slot:Destroy()
4005 end)
4006 end)
4007 end
4008
4009 task.delay(Duration, Dismiss)
4010 Close.Activated:Connect(Dismiss)
4011 TIS(Library._Toasts, Dismiss)
4012
4013 while #Library._Toasts > (Library.MaxNotifications or 4) do
4014 local Oldest = table.remove(Library._Toasts, 1)
4015 if Oldest then Oldest() end
4016 end
4017
4018 return { Dismiss = Dismiss }
4019end
4020
4021Library.Unload = function()
4022 Library.ToggleMenu(false)
4023 if Library.Watermark.Frame then Library.Watermark.Frame.Visible = false end
4024 if Library.KeybindList.Frame then Library.KeybindList.Frame.Visible = false end
4025 if Library._NotifyHost then Library._NotifyHost.Visible = false end
4026 for _, Win in Library.Windows do
4027 if Win.Canvas then
4028 Win.Canvas:Destroy()
4029 end
4030 end
4031 table.clear(Library.Windows)
4032 if Library._Instance then
4033 Library._Instance:Destroy()
4034 end
4035 Library.Notify({ Title = "Noctro"; Text = "Unloaded"; Duration = 2 })
4036end
4037
4038Library.ToggleMenu = function(State: boolean?)
4039 if Library.Auth and Library.Auth.Enabled and not Library.Auth.Validated then
4040 State = true
4041 end
4042 if State == nil then
4043 State = not Library.MenuOpen
4044 end
4045 Library.MenuOpen = State
4046 for _, Win in Library.Windows do
4047 if Win.Canvas then
4048 Win.Canvas.Visible = State
4049 end
4050 end
4051 if Library.OpenPopup and Library.OpenPopup.Close then
4052 Library.OpenPopup.Close()
4053 end
4054end
4055
4056UserInputService.InputBegan:Connect(function(Input, GameProcessed)
4057 if GameProcessed then
4058 return
4059 end
4060 if Library.MenuKey and Input.KeyCode == Library.MenuKey then
4061 Library.ToggleMenu()
4062 end
4063end)
4064
4065Library.BuildConfigPage = function(self: Library, Window: any)
4066 local Page = Window:Page({ Icon = "save" })
4067 local Manager = Page:SubPage({ Name = "Configs" })
4068 local ThemePage = Page:SubPage({ Name = "Theme" })
4069 local MenuPage = Page:SubPage({ Name = "Menu" })
4070
4071 local ListSection = Manager:Section({ Name = "Configs"; Side = "Left"; Icon = "folder" })
4072 local ActionsSection = Manager:Section({ Name = "Actions"; Side = "Right"; Icon = "settings" })
4073 local ThemeSection = ThemePage:Section({ Name = "Colors"; Side = "Left"; Icon = "palette" })
4074 local ThemePrev = ThemePage:Section({ Name = "Preview"; Side = "Right"; Icon = "eye" })
4075 local MenuSection = MenuPage:Section({ Name = "Menu"; Side = "Left"; Icon = "settings" })
4076 local NotifySection = MenuPage:Section({ Name = "Notifications"; Side = "Right"; Icon = "bell" })
4077
4078 local Selected = { Name = nil :: string? }
4079 local ListRows = {} :: { [string]: TextButton }
4080
4081 local ListHost = Add("Frame", {
4082 Parent = ListSection.Content;
4083 Name = "ConfigList";
4084 BackgroundColor3 = Library.Theme.Background;
4085 BorderSizePixel = 0;
4086 Size = UD2(1, 0, 0, 160);
4087 })
4088 Add("UICorner", { Parent = ListHost; CornerRadius = UD(0, 6); })
4089 Add("UIStroke", { Parent = ListHost; ApplyStrokeMode = ASM.Border; Color = Library.Theme.Border; })
4090 local ListScroll = Add("ScrollingFrame", {
4091 Parent = ListHost;
4092 BackgroundTransparency = 1;
4093 BorderSizePixel = 0;
4094 Size = UFS(1, 1);
4095 CanvasSize = UD2(0, 0, 0, 0);
4096 AutomaticCanvasSize = AS.Y;
4097 ScrollBarThickness = 2;
4098 ScrollBarImageColor3 = Library.Theme.Accent;
4099 })
4100 Add("UIListLayout", { Parent = ListScroll; Padding = UD(0, 2); SortOrder = SO.LayoutOrder; })
4101 Add("UIPadding", { Parent = ListScroll; PaddingTop = UD(0, 4); PaddingBottom = UD(0, 4); PaddingLeft = UD(0, 4); PaddingRight = UD(0, 4); })
4102
4103 local function PaintRows()
4104 for Name, Row in ListRows do
4105 local On = Selected.Name == Name
4106 Row.TextColor3 = On and Library.Theme.Accent or RGB(200, 204, 220)
4107 Row.BackgroundTransparency = On and 0.85 or 1
4108 Row.BackgroundColor3 = Library.Theme.Accent
4109 end
4110 end
4111
4112 local function SelectConfig(Name: string)
4113 Selected.Name = Name
4114 if ConfigInput then
4115 ConfigInput.Set(Name)
4116 end
4117 PaintRows()
4118 end
4119
4120 local function RebuildList()
4121 for _, Row in ListRows do
4122 Row:Destroy()
4123 end
4124 table.clear(ListRows)
4125 local Names = Library.ListConfigs()
4126 if #Names == 0 then
4127 local Empty = Add("TextLabel", {
4128 Parent = ListScroll;
4129 BackgroundTransparency = 1;
4130 Size = UD2(1, 0, 0, 28);
4131 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4132 Text = "No configs yet";
4133 TextColor3 = RGB(120, 124, 140);
4134 TextSize = 12;
4135 })
4136 ListRows["__empty"] = Empty :: any
4137 else
4138 for i, Name in Names do
4139 local Row = Add("TextButton", {
4140 Parent = ListScroll;
4141 AutoButtonColor = false;
4142 BackgroundColor3 = Library.Theme.Accent;
4143 BackgroundTransparency = 1;
4144 BorderSizePixel = 0;
4145 Size = UD2(1, 0, 0, 26);
4146 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4147 Text = " " .. Name;
4148 TextColor3 = RGB(200, 204, 220);
4149 TextSize = 13;
4150 TextXAlignment = TXA.Left;
4151 LayoutOrder = i;
4152 })
4153 Add("UICorner", { Parent = Row; CornerRadius = UD(0, 4); })
4154 Row.Activated:Connect(function()
4155 SelectConfig(Name)
4156 end)
4157 ListRows[Name] = Row
4158 end
4159 end
4160 if Selected.Name and ListRows[Selected.Name] then
4161 PaintRows()
4162 elseif #Names > 0 then
4163 SelectConfig(Names[1])
4164 end
4165 end
4166
4167 local ConfigInput = ActionsSection:Input({
4168 Name = "New name (for Save)";
4169 Value = "default";
4170 Placeholder = "name";
4171 Flag = "ConfigName";
4172
4173 })
4174
4175 local function SelectedName(): string?
4176 return Selected.Name
4177 end
4178
4179 ActionsSection:Button({
4180 Name = "Save";
4181 Width = 0.5;
4182 Callback = function()
4183 local Name = Selected.Name
4184 if not Name or Name == "" then
4185 local Typed = ConfigInput and ConfigInput.Value
4186 if type(Typed) == "string" and Typed ~= "" then
4187 Name = Typed
4188 else
4189 Library.Notify({ Title = "Config"; Content = "Select a config or type a name"; Type = "Warning" })
4190 return
4191 end
4192 end
4193 if Library.SaveConfig(Name) then
4194 SelectConfig(Name)
4195 RebuildList()
4196 Library.Notify({ Title = "Config"; Content = "Saved " .. Name; Type = "Success" })
4197 else
4198 Library.Notify({ Title = "Config"; Content = "Save failed — executor FS?"; Type = "Error" })
4199 end
4200 end;
4201 })
4202 ActionsSection:Button({
4203 Name = "Load";
4204 Width = 0.5;
4205 Callback = function()
4206 local Name = SelectedName()
4207 if not Name then
4208 Library.Notify({ Title = "Config"; Content = "Select a config in the list first"; Type = "Warning" })
4209 return
4210 end
4211 if Library.LoadConfig(Name) then
4212 Library.ApplyTheme()
4213 if Library.SyncThemePickers then
4214 Library.SyncThemePickers()
4215 end
4216 SelectConfig(Name)
4217 Library.Notify({ Title = "Config"; Content = "Loaded " .. Name; Type = "Success" })
4218 else
4219 Library.Notify({ Title = "Config"; Content = "Failed to load " .. Name; Type = "Error" })
4220 end
4221 end;
4222 })
4223 ActionsSection:Button({
4224 Name = "Delete";
4225 Width = 0.5;
4226 Callback = function()
4227 local Name = SelectedName()
4228 if not Name then
4229 Library.Notify({ Title = "Config"; Content = "Select a config in the list first"; Type = "Warning" })
4230 return
4231 end
4232 Library.DeleteConfig(Name)
4233 Selected.Name = nil
4234 RebuildList()
4235 Library.Notify({ Title = "Config"; Content = "Deleted " .. Name; Type = "Info" })
4236 end;
4237 })
4238 ActionsSection:Button({
4239 Name = "Refresh";
4240 Width = 0.5;
4241 Callback = function()
4242 RebuildList()
4243 Library.Notify({ Title = "Config"; Content = "List refreshed"; Type = "Info"; Duration = 1.5 })
4244 end;
4245 })
4246 ActionsSection:Button({
4247 Name = "Set autoload";
4248 Callback = function()
4249 local Name = SelectedName()
4250 if not Name then
4251 Library.Notify({ Title = "Config"; Content = "Select a config in the list first"; Type = "Warning" })
4252 return
4253 end
4254 Library.SetAutoload(Name)
4255 Library.Notify({ Title = "Config"; Content = "Autoload set to " .. Name; Type = "Success" })
4256 end;
4257 })
4258
4259 RebuildList()
4260
4261 local ThemePickers = {}
4262
4263 local function ThemePicker(LabelText: string, Key: string)
4264 local Row = ThemeSection:Label({ Text = LabelText })
4265 local Picker = Row:Colorpicker({
4266 Color = Library.Theme[Key];
4267 Flag = "Theme" .. Key;
4268 Callback = function(Color)
4269 Library.Theme[Key] = Color
4270 if Key == "Accent" then
4271 local H, S, V = Color:ToHSV()
4272 Library.Theme.AccentDark = HSV(H, S, math.max(V * 0.55, 0.15))
4273 end
4274 Library.ApplyTheme()
4275 end;
4276 })
4277 ThemePickers[Key] = Picker
4278 end
4279
4280 ThemePicker("Accent", "Accent")
4281 ThemePicker("Background", "Background")
4282 ThemePicker("Surface", "Surface")
4283 ThemePicker("Surface alt", "SurfaceAlt")
4284 ThemePicker("Border", "Border")
4285 ThemePicker("Section border", "SectionBorder")
4286 ThemePicker("Text", "Text")
4287
4288 Library.SyncThemePickers = function()
4289 for Key, Picker in pairs(ThemePickers) do
4290 local Color = Library.Theme[Key]
4291 if Color and Picker and Picker.Set then
4292 Picker.Set(Color, 0)
4293 end
4294 end
4295 end
4296
4297 ThemePrev:Paragraph({
4298 Title = "Live theme";
4299 Body = "Changes apply immediately to the menu, watermark, and keybind list.";
4300 })
4301 ThemePrev:Button({
4302 Name = "Reset theme";
4303 Callback = function()
4304 for Key, Color in pairs(Library.DefaultTheme) do
4305 Library.Theme[Key] = Color
4306 end
4307 Library.ApplyTheme()
4308 if Library.SyncThemePickers then
4309 Library.SyncThemePickers()
4310 end
4311 Library.Notify({ Title = "Theme"; Content = "Reset to default"; Type = "Info" })
4312 end;
4313 })
4314
4315 local MenuKeyLabel = MenuSection:Label({ Text = "Menu key" })
4316 MenuKeyLabel:Keybind({
4317 Title = "Menu";
4318 Key = Library.MenuKey;
4319 Type = "Toggle";
4320 Flag = "MenuKeybind";
4321 Callback = function() end;
4322 })
4323 task.defer(function()
4324 local Flag = Library.Flags["MenuKeybind"]
4325 if Flag then
4326 local OldSet = Flag.Set
4327 Flag.Set = function(Key)
4328 if OldSet then OldSet(Key) end
4329 if Key then Library.MenuKey = Key end
4330 end
4331 end
4332 end)
4333
4334 MenuSection:Slider({
4335 Name = "UI scale";
4336 Suffix = "%";
4337 Value = math.floor(Library.UIScale * 100);
4338 Min = 75;
4339 Max = 125;
4340 Increment = 5;
4341 Flag = "UIScale";
4342 Callback = function(Value)
4343 Library.SetScale(Value / 100)
4344 end;
4345 })
4346 local WM = MenuSection:Label({ Text = "Watermark" })
4347 WM:Toggle({
4348 State = Library.Watermark.Enabled;
4349 Flag = "WatermarkEnabled";
4350 Callback = function(State)
4351 Library.SetWatermark(nil, State)
4352 end;
4353 })
4354 local KBL = MenuSection:Label({ Text = "Keybind list" })
4355 KBL:Toggle({
4356 State = Library.KeybindList.Enabled;
4357 Flag = "KeybindListEnabled";
4358 Callback = function(State)
4359 Library.SetKeybindList(State)
4360 end;
4361 })
4362 MenuSection:Button({
4363 Name = "Hide menu";
4364 Width = 0.5;
4365 Callback = function()
4366 Library.ToggleMenu(false)
4367 Library.Notify({ Title = "Noctro"; Text = "Menu hidden - press menu key"; Duration = 2 })
4368 end;
4369 })
4370 MenuSection:Button({
4371 Name = "Unload";
4372 Width = 0.5;
4373 Callback = function()
4374 Library.Unload()
4375 end;
4376 })
4377 if Library.Auth and Library.Auth.Enabled then
4378 MenuSection:Button({
4379 Name = "Sign out";
4380 Callback = function()
4381 Library.SignOut()
4382 end;
4383 })
4384 end
4385
4386 NotifySection:Dropdown({
4387 Name = "Position";
4388 Options = { "Top Left", "Top Right", "Bottom Left", "Bottom Right" };
4389 Value = Library.NotifyPosition;
4390 Flag = "NotifyPosition";
4391 Callback = function(Value)
4392 Library.NotifyPosition = Value
4393 end;
4394 })
4395 local NT = NotifySection:Label({ Text = "Notify on toggles" })
4396 NT:Toggle({
4397 State = Library.NotifyToggles ~= false;
4398 Flag = "NotifyToggles";
4399 Callback = function(State)
4400 Library.NotifyToggles = State
4401 end;
4402 })
4403 NotifySection:Button({
4404 Name = "Test notification";
4405 Callback = function()
4406 Library.Notify({ Title = "Noctro"; Text = "This is a test notification"; Type = "Success" })
4407 end;
4408 })
4409
4410 local Autoload = Library.GetAutoload()
4411 if Autoload then
4412 Library.LoadConfig(Autoload)
4413 Library.ApplyTheme()
4414 if Library.SyncThemePickers then
4415 Library.SyncThemePickers()
4416 end
4417 SelectConfig(Autoload)
4418 end
4419
4420 return Page
4421end
4422
4423
4424Library.FormatExpiry = function(ExpiresAt)
4425 if not ExpiresAt or type(ExpiresAt) ~= "number" then
4426 return "Lifetime"
4427 end
4428 local Left = math.floor(ExpiresAt - os.time())
4429 if Left <= 0 then
4430 return "Expired"
4431 end
4432 local Days = math.floor(Left / 86400)
4433 local Hours = math.floor((Left % 86400) / 3600)
4434 local Mins = math.floor((Left % 3600) / 60)
4435 local Parts = {}
4436 if Days > 0 then
4437 table.insert(Parts, string.format("%dd", Days))
4438 end
4439 if Hours > 0 then
4440 table.insert(Parts, string.format("%dh", Hours))
4441 end
4442 if Mins > 0 and Days == 0 then
4443 table.insert(Parts, string.format("%dm", Mins))
4444 end
4445 if #Parts == 0 then
4446 return "1m"
4447 end
4448 return table.concat(Parts, " ")
4449end
4450
4451Library.GetKeyExpiryText = function()
4452 if not Library.Auth or not Library.Auth.Validated then
4453 return ""
4454 end
4455 return Library.FormatExpiry(Library.Auth.ExpiresAt)
4456end
4457
4458Library.KeySystem = function(self, propertyTable)
4459 local Opts = Overwrite({
4460 Title = "Login";
4461 Note = "";
4462 Placeholder = "License key";
4463 ButtonText = "Sign in";
4464 Remember = true;
4465 RememberFile = "auth_key.txt";
4466 ShowExpiry = true;
4467 WatermarkExpiry = false;
4468 GetKey = nil;
4469 Validate = nil;
4470 }, propertyTable or {})
4471
4472 Library.Auth.Enabled = true
4473 Library.Auth.Validated = false
4474 Library.Auth.Token = nil
4475 Library.Auth.ExpiresAt = nil
4476 Library.Auth.ShowExpiry = Opts.ShowExpiry == true
4477 Library.Auth.WatermarkExpiry = Opts.WatermarkExpiry == true
4478 Library.Auth.Options = Opts
4479 return Opts
4480end
4481
4482local function AuthRememberPath()
4483 local Opts = Library.Auth and Library.Auth.Options
4484 local Name = (Opts and Opts.RememberFile) or "auth_key.txt"
4485 return Library.Folder .. "/" .. Name
4486end
4487
4488local function ReadRememberedKey()
4489 if not HasFS() then
4490 return nil
4491 end
4492 local Path = AuthRememberPath()
4493 local Ok, Data = pcall(function()
4494 if isfile and isfile(Path) then
4495 return readfile(Path)
4496 end
4497 return nil
4498 end)
4499 if Ok and type(Data) == "string" and Data ~= "" then
4500 return Data
4501 end
4502 return nil
4503end
4504
4505local function WriteRememberedKey(Key, Remember)
4506 if not HasFS() then
4507 return
4508 end
4509 EnsureFolder()
4510 local Path = AuthRememberPath()
4511 if Remember and Key and Key ~= "" then
4512 pcall(writefile, Path, Key)
4513 else
4514 pcall(function()
4515 if isfile and isfile(Path) and delfile then
4516 delfile(Path)
4517 elseif writefile then
4518 writefile(Path, "")
4519 end
4520 end)
4521 end
4522end
4523
4524local function RunValidate(Key, Finish)
4525 local Opts = Library.Auth.Options
4526 if not Opts or type(Opts.Validate) ~= "function" then
4527 Finish(true, nil, nil)
4528 return
4529 end
4530 local called = false
4531 local function SafeFinish(Success, ExpiresAt, Err)
4532 if called then return end
4533 called = true
4534 Finish(Success, ExpiresAt, Err)
4535 end
4536 local Ok, A, B, C = pcall(function()
4537 return Opts.Validate(Key, SafeFinish)
4538 end)
4539 if not Ok then
4540 SafeFinish(false, nil, tostring(A))
4541 return
4542 end
4543 if A == true or A == false then
4544 SafeFinish(A, B, C)
4545 end
4546end
4547
4548
4549Library.SignOut = function()
4550 if not Library.Auth or not Library.Auth.Enabled then
4551 return
4552 end
4553 WriteRememberedKey(nil, false)
4554 Library.Auth.Validated = false
4555 Library.Auth.Token = nil
4556 Library.Auth.ExpiresAt = nil
4557 for _, Win in Library.Windows do
4558 if Win.Canvas then
4559 local Footer = Win.Canvas:FindFirstChild("Footer")
4560 if Footer then
4561 local Exp = Footer:FindFirstChild("KeyExpiry")
4562 if Exp then Exp:Destroy() end
4563 end
4564 if Library._MountKeySystem then
4565 Library._MountKeySystem(Win)
4566 end
4567 end
4568 end
4569 Library.Notify({ Title = "Key system"; Content = "Signed out"; Type = "Info"; Duration = 2 })
4570end
4571
4572Library._MountKeySystem = function(Window)
4573 if not Library.Auth or not Library.Auth.Enabled or Library.Auth.Validated then
4574 return
4575 end
4576 local Canvas = Window and Window.Canvas
4577 if not Canvas then
4578 return
4579 end
4580 local Opts = Library.Auth.Options or {}
4581 local T = Library.Theme
4582
4583 local Hidden = {}
4584 for _, Ch in ipairs(Canvas:GetChildren()) do
4585 if Ch:IsA("GuiObject") and Ch.Name ~= "UIScale" then
4586 Hidden[Ch] = Ch.Visible
4587 Ch.Visible = false
4588 end
4589 end
4590
4591 task.defer(function()
4592 local Camera = workspace.CurrentCamera
4593 if Camera and Canvas.Parent then
4594 local Viewport = Camera.ViewportSize
4595 local Size = Canvas.AbsoluteSize
4596 if Size.X <= 0 then Size = V2(658, 461) end
4597 local GuiService = Services:GetService("GuiService")
4598 local Inset = GuiService:GetGuiInset()
4599 Canvas.Position = ClampToScreen(Canvas, UFO(
4600 math.floor((Viewport.X - Size.X) * 0.5),
4601 math.floor((Viewport.Y - Inset.Y - Size.Y) * 0.5)
4602 ))
4603 end
4604 end)
4605
4606 local Layer = Add("Frame", {
4607 Parent = Canvas;
4608 Name = "KeySystem";
4609 Size = UFS(1, 1);
4610 BackgroundColor3 = T.Background or RGB(9, 8, 8);
4611 BorderSizePixel = 0;
4612 ZIndex = 80;
4613 Active = true;
4614 })
4615 Add("UICorner", { Parent = Layer; CornerRadius = UD(0, 5); })
4616 Add("UIStroke", { Parent = Layer; ApplyStrokeMode = ASM.Border; Color = T.Border or RGB(36, 37, 37); })
4617 Add("UIShadow", { Parent = Layer; BlurRadius = UD(0, 20); Spread = UFO(5, 5); Transparency = 0.65; })
4618 Library.ThemeLink(Layer, "BackgroundColor3", "Background")
4619 BindDrag(Canvas, Layer, true)
4620
4621 local Hair = Add("Frame", {
4622 Parent = Layer;
4623 Size = UD2(1, 0, 0, 1);
4624 BackgroundColor3 = RGB(255, 255, 255);
4625 BackgroundTransparency = 0.93;
4626 BorderSizePixel = 0;
4627 ZIndex = 81;
4628 })
4629
4630 local AccentGlow = Add("ImageLabel", {
4631 Parent = Layer;
4632 AnchorPoint = V2(0.5, 0.5);
4633 Position = UFS(0.5, 0.42);
4634 Size = UFO(480, 360);
4635 BackgroundTransparency = 1;
4636 Image = "rbxassetid://8992230677";
4637 ImageColor3 = T.Accent;
4638 ImageTransparency = 0.9;
4639 ZIndex = 80;
4640 })
4641 Library.ThemeLink(AccentGlow, "ImageColor3", "Accent")
4642
4643 local SideGlow = Add("ImageLabel", {
4644 Parent = Layer;
4645 AnchorPoint = V2(0, 1);
4646 Position = UD2(0, -20, 1, 20);
4647 Size = UFO(220, 180);
4648 BackgroundTransparency = 1;
4649 Image = "rbxassetid://8992230677";
4650 ImageColor3 = T.AccentDark or T.Accent;
4651 ImageTransparency = 0.92;
4652 ZIndex = 80;
4653 })
4654
4655 local Form = Add("Frame", {
4656 Parent = Layer;
4657 AnchorPoint = V2(0.5, 0.5);
4658 Position = UFS(0.5, 0.5);
4659 Size = UFO(300, 0);
4660 AutomaticSize = AS.Y;
4661 BackgroundTransparency = 1;
4662 ZIndex = 81;
4663 })
4664
4665 Add("TextLabel", {
4666 Parent = Form;
4667 BackgroundTransparency = 1;
4668 Size = UD2(1, 0, 0, 28);
4669 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4670 Text = Opts.Title or "Login";
4671 TextColor3 = T.Text or RGB(255, 255, 255);
4672 TextSize = 22;
4673 ZIndex = 82;
4674 })
4675
4676 local Under = Add("Frame", {
4677 Parent = Form;
4678 AnchorPoint = V2(0.5, 0);
4679 Position = UD2(0.5, 0, 0, 32);
4680 Size = UFO(56, 2);
4681 BackgroundColor3 = T.Accent;
4682 BorderSizePixel = 0;
4683 ZIndex = 82;
4684 })
4685 Library.ThemeLink(Under, "BackgroundColor3", "Accent")
4686
4687 local KeyWrap = Add("Frame", {
4688 Parent = Form;
4689 Position = UFO(0, 52);
4690 Size = UD2(1, 0, 0, 42);
4691 BackgroundColor3 = T.Surface or RGB(15, 14, 15);
4692 BorderSizePixel = 0;
4693 ZIndex = 82;
4694 })
4695 Add("UICorner", { Parent = KeyWrap; CornerRadius = UD(0, 6); })
4696 Add("UIStroke", { Parent = KeyWrap; ApplyStrokeMode = ASM.Border; Color = T.Border or RGB(36, 37, 37); })
4697 Library.ThemeLink(KeyWrap, "BackgroundColor3", "Surface")
4698 local KeyIcon = Add("ImageLabel", {
4699 Parent = KeyWrap;
4700 AnchorPoint = V2(0, 0.5);
4701 Position = UD2(0, 12, 0.5, 0);
4702 Size = UFO(14, 14);
4703 BackgroundTransparency = 1;
4704 ImageColor3 = RGB(140, 144, 155);
4705 ZIndex = 83;
4706 })
4707 pcall(function() KeyIcon.Image = ResolveIcon("key-round") end)
4708 local KeyBox = Add("TextBox", {
4709 Parent = KeyWrap;
4710 Position = UFO(36, 0);
4711 Size = UD2(1, -48, 1, 0);
4712 BackgroundTransparency = 1;
4713 PlaceholderText = Opts.Placeholder or "License key";
4714 PlaceholderColor3 = RGB(120, 124, 135);
4715 Text = "";
4716 TextColor3 = T.Text;
4717 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4718 TextSize = 13;
4719 TextXAlignment = TXA.Left;
4720 ClearTextOnFocus = false;
4721 ZIndex = 83;
4722 })
4723
4724 local SignIn = Add("TextButton", {
4725 Parent = Form;
4726 Position = UFO(0, 106);
4727 Size = UD2(1, 0, 0, 42);
4728 BackgroundColor3 = RGB(255, 255, 255);
4729 AutoButtonColor = false;
4730 Text = Opts.ButtonText or "Sign in";
4731 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4732 TextSize = 14;
4733 TextColor3 = RGB(0, 0, 0);
4734 BorderSizePixel = 0;
4735 ZIndex = 82;
4736 })
4737 Add("UICorner", { Parent = SignIn; CornerRadius = UD(0, 6); })
4738 local SignGrad = Add("UIGradient", {
4739 Parent = SignIn;
4740 Color = CS{ CSK(0, T.AccentDark or RGB(78, 88, 129)), CSK(1, T.Accent or RGB(138, 156, 229)) };
4741 Rotation = -70;
4742 })
4743 Library.ThemeLink(SignGrad, "Gradient", "AccentDark", "Accent")
4744
4745 local RememberOn = Opts.Remember ~= false
4746 local RememberRow = Add("Frame", {
4747 Parent = Form;
4748 Position = UFO(0, 158);
4749 Size = UD2(1, 0, 0, 20);
4750 BackgroundTransparency = 1;
4751 ZIndex = 82;
4752 })
4753 local RememberBtn = Add("TextButton", {
4754 Parent = RememberRow;
4755 Size = UFO(18, 18);
4756 BackgroundColor3 = T.Surface or RGB(15, 14, 15);
4757 Text = "";
4758 AutoButtonColor = false;
4759 BorderSizePixel = 0;
4760 ZIndex = 83;
4761 })
4762 Add("UICorner", { Parent = RememberBtn; CornerRadius = UD(0, 4); })
4763 local RemStroke = Add("UIStroke", { Parent = RememberBtn; Color = T.Border or RGB(36, 37, 37); Thickness = 1; })
4764 local Check = Add("TextLabel", {
4765 Parent = RememberBtn;
4766 Size = UFS(1, 1);
4767 BackgroundTransparency = 1;
4768 Text = "✓";
4769 TextColor3 = T.Accent;
4770 TextSize = 13;
4771 Font = Enum.Font.GothamBold;
4772 TextTransparency = RememberOn and 0 or 1;
4773 ZIndex = 84;
4774 })
4775 if RememberOn then
4776 RememberBtn.BackgroundColor3 = T.Accent
4777 Check.TextColor3 = RGB(255, 255, 255)
4778 RemStroke.Transparency = 1
4779 end
4780 Add("TextLabel", {
4781 Parent = RememberRow;
4782 Position = UFO(22, 0);
4783 Size = UD2(1, -22, 1, 0);
4784 BackgroundTransparency = 1;
4785 Text = "Remember me";
4786 TextColor3 = RGB(160, 160, 165);
4787 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4788 TextSize = 12;
4789 TextXAlignment = TXA.Left;
4790 ZIndex = 83;
4791 })
4792 RememberBtn.Activated:Connect(function()
4793 RememberOn = not RememberOn
4794 Tween(RememberBtn, { BackgroundColor3 = RememberOn and Library.Theme.Accent or Library.Theme.Surface }, 0.12)
4795 Tween(Check, { TextTransparency = RememberOn and 0 or 1; TextColor3 = RememberOn and RGB(255, 255, 255) or Library.Theme.Accent }, 0.12)
4796 Tween(RemStroke, { Transparency = RememberOn and 1 or 0 }, 0.12)
4797 end)
4798
4799 local Error = Add("TextLabel", {
4800 Parent = Form;
4801 Position = UFO(0, 198);
4802 Size = UD2(1, 0, 0, 16);
4803 BackgroundTransparency = 1;
4804 Text = "";
4805 TextColor3 = RGB(240, 120, 120);
4806 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4807 TextSize = 12;
4808 ZIndex = 82;
4809 })
4810
4811 local NoteY = 178
4812 if type(Opts.GetKey) == "string" and Opts.GetKey ~= "" then
4813 local GetBtn = Add("TextButton", {
4814 Parent = Form;
4815 Position = UFO(0, NoteY);
4816 Size = UD2(1, 0, 0, 16);
4817 BackgroundTransparency = 1;
4818 Text = "Get a key";
4819 TextColor3 = T.Accent;
4820 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4821 TextSize = 12;
4822 AutoButtonColor = false;
4823 ZIndex = 82;
4824 })
4825 GetBtn.Activated:Connect(function()
4826 pcall(function()
4827 if setclipboard then
4828 setclipboard(Opts.GetKey)
4829 Library.Notify({ Title = "Key system"; Content = "Link copied"; Type = "Info"; Duration = 2 })
4830 end
4831 end)
4832 end)
4833 end
4834
4835 local Loading = Add("Frame", {
4836 Parent = Canvas;
4837 Name = "AuthLoading";
4838 Size = UFS(1, 1);
4839 BackgroundColor3 = T.Background or RGB(9, 8, 8);
4840 BorderSizePixel = 0;
4841 Visible = false;
4842 ZIndex = 90;
4843 })
4844 Add("UICorner", { Parent = Loading; CornerRadius = UD(0, 5); })
4845 Add("UIStroke", { Parent = Loading; ApplyStrokeMode = ASM.Border; Color = T.Border or RGB(36, 37, 37); })
4846 Add("UIShadow", { Parent = Loading; BlurRadius = UD(0, 20); Spread = UFO(5, 5); Transparency = 0.65; })
4847 Library.ThemeLink(Loading, "BackgroundColor3", "Background")
4848 local Spin = Add("ImageLabel", {
4849 Parent = Loading;
4850 AnchorPoint = V2(0.5, 0.5);
4851 Position = UD2(0.5, 0, 0.48, 0);
4852 Size = UFO(40, 40);
4853 BackgroundTransparency = 1;
4854 Image = "rbxassetid://4965945816";
4855 ImageColor3 = T.Accent;
4856 ZIndex = 91;
4857 })
4858 Library.ThemeLink(Spin, "ImageColor3", "Accent")
4859 Add("TextLabel", {
4860 Parent = Loading;
4861 AnchorPoint = V2(0.5, 0);
4862 Position = UD2(0.5, 0, 0.48, 28);
4863 Size = UFO(160, 18);
4864 BackgroundTransparency = 1;
4865 Text = "Signing in...";
4866 TextColor3 = RGB(160, 160, 165);
4867 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4868 TextSize = 13;
4869 ZIndex = 91;
4870 })
4871 local SpinConn = RunService.RenderStepped:Connect(function(dt)
4872 if Loading.Visible then
4873 Spin.Rotation = (Spin.Rotation + dt * 240) % 360
4874 end
4875 end)
4876
4877 local function RevealMenu()
4878 Layer:Destroy()
4879 Loading:Destroy()
4880 if SpinConn then SpinConn:Disconnect() end
4881 for Ch, Vis in pairs(Hidden) do
4882 if Ch and Ch.Parent then
4883 Ch.Visible = Vis ~= false
4884 end
4885 end
4886 if Library.Auth.ShowExpiry and Library.Auth.ExpiresAt and Window.Canvas then
4887 local Footer = Window.Canvas:FindFirstChild("Footer")
4888 if Footer then
4889 local Exp = Footer:FindFirstChild("KeyExpiry")
4890 if not Exp then
4891 Exp = Add("TextLabel", {
4892 Parent = Footer;
4893 Name = "KeyExpiry";
4894 AnchorPoint = V2(0.5, 0.5);
4895 Position = UFS(0.5, 0.5);
4896 AutomaticSize = AS.X;
4897 Size = UFO(0, 13);
4898 BackgroundTransparency = 1;
4899 FontFace = FN("rbxassetid://12187365364", FW.SemiBold, FS.Normal);
4900 TextColor3 = Library.Theme.Accent;
4901 TextSize = 12;
4902 TextTransparency = 0.15;
4903 })
4904 Library.ThemeLink(Exp, "TextColor3", "Accent")
4905 end
4906 local function Tick()
4907 if not Exp or not Exp.Parent then return end
4908 Exp.Text = "Key · " .. Library.FormatExpiry(Library.Auth.ExpiresAt)
4909 if Library.Auth.ExpiresAt and os.time() >= Library.Auth.ExpiresAt then
4910 Library.Auth.Validated = false
4911 Library.Auth.Token = nil
4912 Library.Notify({ Title = "Key system"; Content = "License expired"; Type = "Error" })
4913 pcall(function() Library.Unload() end)
4914 end
4915 end
4916 Tick()
4917 task.spawn(function()
4918 while Exp and Exp.Parent and Library.Auth and Library.Auth.Validated do
4919 Tick()
4920 task.wait(30)
4921 end
4922 end)
4923 end
4924 end
4925 if Library.Auth.WatermarkExpiry and Library.SetWatermark then
4926 local Base = Library.Watermark.BaseText or Library.Watermark.Text or "Noctro"
4927 Library.SetWatermark(Base, Library.Watermark.Enabled)
4928 end
4929 Library.Notify({ Title = "Key system"; Content = "Welcome back"; Type = "Success"; Duration = 2.5 })
4930 end
4931
4932 local Busy = false
4933 local function Attempt(Key)
4934 if Busy then return end
4935 Key = tostring(Key or ""):gsub("^%s+", ""):gsub("%s+$", "")
4936 if Key == "" then
4937 Error.Text = "Enter a license key."
4938 return
4939 end
4940 Busy = true
4941 Error.Text = ""
4942 Layer.Visible = false
4943 Loading.Visible = true
4944
4945 local finished = false
4946 local function Finish(Success, ExpiresAt, Err)
4947 if finished then return end
4948 finished = true
4949 if Success then
4950 Library.Auth.Validated = true
4951 Library.Auth.Token = tostring(os.clock()) .. tostring(math.random(100000, 999999))
4952 Library.Auth.ExpiresAt = (type(ExpiresAt) == "number" and ExpiresAt) or nil
4953 WriteRememberedKey(Key, RememberOn)
4954 task.delay(0.55, RevealMenu)
4955 else
4956 Loading.Visible = false
4957 Layer.Visible = true
4958 Error.Text = Err or "Invalid key."
4959 Busy = false
4960 end
4961 end
4962
4963 task.spawn(function()
4964 RunValidate(Key, Finish)
4965 end)
4966 end
4967
4968 SignIn.Activated:Connect(function()
4969 Attempt(KeyBox.Text)
4970 end)
4971 KeyBox.FocusLost:Connect(function(Enter)
4972 if Enter then Attempt(KeyBox.Text) end
4973 end)
4974
4975 local Saved = ReadRememberedKey()
4976 if Saved then
4977 KeyBox.Text = Saved
4978 task.defer(function() Attempt(Saved) end)
4979 end
4980end
4981
4982
4983return Library
4984