BarneyAndFriends

Sentinel Only

May 28th, 2020
23
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 74.41 KB | None | 0 0
  1. -- explorer v1
  2. -- dont mind messy code most was written while doing an all nighter
  3. -- frosty
  4.  
  5. local RunService = game:GetService("RunService");
  6. local ContextAction = game:GetService("ContextActionService")
  7. local UserInputService = game:GetService("UserInputService");
  8. local HttpService = game:GetService("HttpService");
  9. local TweenService = game:GetService("TweenService");
  10. local ReplicatedStorage = game:GetService("ReplicatedStorage");
  11. local Players = game:GetService("Players");
  12.  
  13. local Client = Players.LocalPlayer;
  14. local Mouse = Client:GetMouse();
  15.  
  16. -- retrieve gui
  17. local Gui;
  18.  
  19. -- gotta keep it studio friendly;
  20. if RunService:IsStudio() then
  21. Gui = script.Parent:WaitForChild("Screen");
  22. else
  23. Gui = game:GetObjects("rbxassetid://4840423175")[1];
  24. if not getgenv().SENTINEL_V2 and not getgenv().SENTINEL_LOADED then return end
  25. end
  26.  
  27. local ExplorerFrame = Gui:WaitForChild("Explorer");
  28. local PropertiesFrame = Gui:WaitForChild("Properties");
  29. local TemplateFrame = Gui:waitForChild("ColorFrame"):Clone();
  30.  
  31. local Dropdown = ExplorerFrame:WaitForChild("Dropdown");
  32. local DropdownList = Dropdown:WaitForChild("List");
  33. local DropdownSlot = DropdownList:WaitForChild("Slot");
  34. local SlotTemplate = DropdownSlot:Clone();
  35. local SlotSize = DropdownSlot.AbsoluteSize;
  36. DropdownSlot:Destroy();
  37.  
  38. local Explorer = ExplorerFrame:WaitForChild("Explorer");
  39. local FilterFrame = ExplorerFrame:WaitForChild("FilterFrame");
  40. local ExplorerExitButton = ExplorerFrame:WaitForChild("Exit");
  41. local FilterInput = FilterFrame:WaitForChild("Filter");
  42. local List = Explorer:WaitForChild("List");
  43. local Scrollbar = Explorer:WaitForChild("Scrollbar");
  44. local UpArrow = Scrollbar:WaitForChild("UpArrow");
  45. local DownArrow = Scrollbar:WaitForChild("DownArrow");
  46. local Zone = Scrollbar:WaitForChild("Zone");
  47. local ScrollButton = Zone:WaitForChild("Button");
  48. local ExplorerTitle = ExplorerFrame:WaitForChild("Title");
  49.  
  50. local Properties = PropertiesFrame:WaitForChild("Properties");
  51. local PropertyTitle = PropertiesFrame:WaitForChild("Title");
  52. local PropertiesList = Properties:WaitForChild("List");
  53. local PropertySlot = PropertiesList:WaitForChild("Slot1");
  54. local PropertyTemplate = PropertySlot:Clone();
  55. local PropertySize = PropertySlot.AbsoluteSize;
  56. PropertySlot:Destroy(); PropertySlot = nil;
  57.  
  58. local Template = List:WaitForChild("Slot1");
  59. local TemplateSize = Template.AbsoluteSize;
  60. local ObjectTemplate = Template:Clone();
  61. Template:Destroy(); Template = nil;
  62.  
  63. local SelectionColor = Color3.fromRGB(11, 90, 175);
  64. local HoverColor = Color3.fromRGB(66, 66, 66);
  65. local TextColor = Color3.fromRGB(226, 226, 226);
  66. local ReadOnlyColor = Color3.fromRGB(140, 140, 140);
  67. local CheckmarkBlue = Color3.fromRGB(53, 178, 251);
  68. local CheckmarkBackground = Color3.fromRGB(37, 37, 37);
  69. local ExitRed = Color3.fromRGB(255, 51, 51);
  70.  
  71.  
  72. -- for the um filter thingy
  73. local CustomShowList, CustomChildrenShowing, OnlyShow = nil, nil, nil;
  74.  
  75. local Start = 1; -- <- this start is the index of where the Explorer Scrollbar is at
  76. local START = tick();
  77.  
  78. -- list of services to show
  79. local services = {
  80. "Workspace", "Players",
  81. not RunService:IsStudio() and "CoreGui" or nil,
  82. "Lighting", "ReplicatedFirst", "ReplicatedStorage", "StarterGui",
  83. "StarterPack", "StarterPlayer", "Teams", "SoundService", "Chat"
  84. };
  85.  
  86. local ChildrenShowing = {};
  87. local UpdateList, GetShowList, UpdateScrollbar;
  88. local LoadProperties;
  89. local ListObjects = {};
  90. local ScriptEditor = {};
  91. local ChildAddedUpdates, ScrollUpdates, Selection = {}, {}, {};
  92. local ExplorerHovering, PropertiesHovering = false, false;
  93. local HoverEnd = 175; -- AbsolutePos.X + HoverEnd
  94. local clipboard = nil;
  95. local wrap = coroutine.wrap;
  96.  
  97. -- detectable
  98. local SelectionBox;
  99. if Drawing then
  100. SelectionBox = {
  101. Adornee = nil
  102. };
  103.  
  104. coroutine.wrap(function()
  105. local function wtvp(...) return workspace.CurrentCamera:WorldToViewportPoint(...) end
  106.  
  107. local objects = {};
  108. for i = 1, 12 do
  109. local Line = Drawing.new("Line");
  110. Line.Thickness = 2;
  111. Line.Color = CheckmarkBlue;
  112. objects[("Line%d"):format(i)] = Line;
  113. end
  114.  
  115. while true do
  116. if SelectionBox.Adornee and object:IsA("BasePart") then
  117. local object = SelectionBox.Adornee;
  118.  
  119. local cf = object.CFrame;
  120. local _, on_screen = wtvp(cf.p);
  121.  
  122. if on_screen then
  123. local size = object.Size;
  124. local x, y, z = size.X, size.Y, size.Z;
  125. local v3 = CFrame.new;
  126. -- front
  127. local front_top_left, front_top_left_showing = wtvp((cf * v3(-(x / 2), y / 2, z / 2)).p);
  128. local front_top_right, front_top_right_showing = wtvp((cf * v3(x / 2, y / 2, z / 2)).p);
  129. local front_bottom_left, front_bottom_left_showing = wtvp((cf * v3(-(x / 2), -(y / 2), z / 2)).p);
  130. local front_bottom_right, front_bottom_right_showing = wtvp((cf * v3(x / 2, -(y / 2), z / 2)).p);
  131. front_top_left = Vector2.new(front_top_left.X, front_top_left.Y);
  132. front_top_right = Vector2.new(front_top_right.X, front_top_right.Y);
  133. front_bottom_left = Vector2.new(front_bottom_left.X, front_bottom_left.Y);
  134. front_bottom_right = Vector2.new(front_bottom_right.X, front_bottom_right.Y);
  135. -- back
  136. local back_top_left, back_top_left_showing = wtvp((cf * v3(-(x / 2), y / 2, -(z / 2))).p);
  137. local back_top_right, back_top_right_showing = wtvp((cf * v3(x / 2, y / 2, -(z / 2))).p);
  138. local back_bottom_left, back_bottom_left_showing = wtvp((cf * v3(-(x / 2), -(y / 2), -(z / 2))).p);
  139. local back_bottom_right, back_bottom_right_showing = wtvp((cf * v3(x / 2, -(y / 2), -(z / 2))).p);
  140. back_top_left = Vector2.new(back_top_left.X, back_top_left.Y);
  141. back_top_right = Vector2.new(back_top_right.X, back_top_right.Y);
  142. back_bottom_left = Vector2.new(back_bottom_left.X, back_bottom_left.Y);
  143. back_bottom_right = Vector2.new(back_bottom_right.X, back_bottom_right.Y);
  144.  
  145. objects.Line1.From = front_top_left;
  146. objects.Line1.To = front_top_right;
  147. objects.Line1.Visible = front_top_right_showing;
  148.  
  149. objects.Line2.From = front_top_right;
  150. objects.Line2.To = front_bottom_right;
  151. objects.Line2.Visible = front_bottom_right_showing;
  152.  
  153. objects.Line3.From = front_bottom_right;
  154. objects.Line3.To = front_bottom_left;
  155. objects.Line3.Visible = front_bottom_left_showing;
  156.  
  157. objects.Line4.From = front_bottom_left;
  158. objects.Line4.To = front_top_left;
  159. objects.Line4.Visible = front_top_left_showing;
  160.  
  161. objects.Line5.From = back_top_left;
  162. objects.Line5.To = back_top_right;
  163. objects.Line5.Visible = back_top_right_showing;
  164.  
  165. objects.Line6.From = back_top_right;
  166. objects.Line6.To = back_bottom_right;
  167. objects.Line6.Visible = back_bottom_right_showing;
  168.  
  169. objects.Line7.From = back_bottom_right;
  170. objects.Line7.To = back_bottom_left;
  171. objects.Line7.Visible = back_bottom_left_showing;
  172.  
  173. objects.Line8.From = back_bottom_left;
  174. objects.Line8.To = back_top_left;
  175. objects.Line8.Visible = back_top_left_showing;
  176.  
  177. -- connections
  178.  
  179. objects.Line9.From = back_bottom_left;
  180. objects.Line9.To = front_bottom_left;
  181. objects.Line9.Visible = front_bottom_left_showing;
  182.  
  183. objects.Line10.From = back_bottom_right;
  184. objects.Line10.To = front_bottom_right;
  185. objects.Line10.Visible = front_bottom_right_showing;
  186.  
  187. objects.Line11.From = back_top_left;
  188. objects.Line11.To = front_top_left;
  189. objects.Line11.Visible = front_top_left_showing;
  190.  
  191. objects.Line12.From = front_top_right;
  192. objects.Line12.To = back_top_right;
  193. objects.Line12.Visible = back_bottom_right_showing;
  194. else
  195. for i = 1, 12 do
  196. objects[("Line%d"):format(i)].Visible = false
  197. end
  198. end
  199. RunService.RenderStepped:Wait();
  200. else
  201. for i = 1, 12 do
  202. objects[("Line%d"):format(i)].Visible = false
  203. end
  204. wait(0.1);
  205. end
  206. end
  207. end)()
  208. else
  209. -- is detectable if exploit does not support the Drawing api
  210. SelectionBox = Instance.new("SelectionBox");
  211. SelectionBox.LineThickness = 0.05;
  212. SelectionBox.Color3 = CheckmarkBlue;
  213. SelectionBox.Parent = Gui;
  214. end
  215.  
  216.  
  217. local CurrentZIndexPriority = 1; -- for windows
  218.  
  219. local TotalObjects = #workspace:GetDescendants();
  220.  
  221. -- GetFromDump is for if it should get the latest updated properties directly from the roblox api dump
  222. -- this is disabled because it causes slight lag at startup because of JSONDecoding such a huge JSON file
  223. -- i should be hopefully maintaining my github's property page fairly often
  224. local GetFromDump = false;
  225.  
  226. local HttpGet;
  227. local ApiDump, ClassProperties;
  228.  
  229. local ExitButton;
  230.  
  231. -- still keeping it studio friendly
  232. if not RunService:IsStudio() then
  233. HttpGet = function(url) return game:HttpGet(url) end;
  234. end
  235.  
  236. if RunService:IsStudio() then
  237. ApiDump = require(ReplicatedStorage:WaitForChild("ApiDump"));
  238. elseif GetFromDump then
  239. local proxy = "https://s3.amazonaws.com/";
  240. local version = HttpGet(proxy .. "setup.roblox.com/versionQTStudio");
  241. ApiDump = HttpGet(proxy .. "setup.roblox.com/"..version.."-API-Dump.json");
  242. end
  243.  
  244.  
  245. -- decoding json
  246. do
  247. -- get auto updated dump
  248. if GetFromDump then
  249. local JsonDecoded = HttpService:JSONDecode(ApiDump);
  250. local Classes = JsonDecoded.Classes;
  251. local ClassesDictionary = {};
  252. local WaitingForInherit = {};
  253.  
  254. -- this basically ends up formatting the API dump into a properties list
  255. -- this is what my properties table on the github is
  256.  
  257. local function HasTag(Data, Tag)
  258. for _, tag in pairs(Data.Tags or {}) do
  259. if tag == Tag then
  260. return true;
  261. end
  262. end
  263. return false;
  264. end
  265.  
  266. for _, class in pairs(Classes) do
  267. local Super, Members, Name = class.Superclass, class.Members, class.Name;
  268. local properties = {};
  269. for _, member in pairs(Members) do
  270. local Category, Type, Name = member.Category, member.MemberType, member.Name;
  271. if Type == "Property" and HasTag(member, "Hidden") == false then
  272. local property = {Name = Name, Category = Category};
  273. if HasTag(member, "Deprecated") then
  274. property.Deprecated = true;
  275. end
  276. property.ValueType = member.ValueType.Name;
  277. if member.Security.Write ~= "None" or HasTag(member, "ReadOnly") then
  278. property.ReadOnly = true;
  279. end
  280. properties[Name] = property;
  281. end
  282. end
  283. WaitingForInherit[Name] = Super;
  284. ClassesDictionary[Name] = {Super = Super, Properties = properties, Name = Name};
  285. end
  286.  
  287. local function GetLength(List)
  288. local Num = 0;
  289. for k, v in pairs(List) do Num = Num + 1 end;
  290. return Num
  291. end
  292.  
  293. -- made this more efficient in my js code kinda too lazy to update it
  294. while GetLength(WaitingForInherit) ~= 0 do
  295. for Name, Super in pairs(WaitingForInherit) do
  296. if not WaitingForInherit[Super] then
  297. for name, property in pairs((ClassesDictionary[Super] or {}).Properties or {}) do
  298. ClassesDictionary[Name].Properties[name] = property;
  299. end
  300. WaitingForInherit[Name] = nil;
  301. end
  302. end
  303. end
  304.  
  305. ClassProperties = ClassesDictionary;
  306. else
  307. -- gotta keep it studio safe!
  308. if RunService:IsStudio() then
  309. ClassProperties = require(ReplicatedStorage:WaitForChild("ClassProperties"));
  310. else
  311. ClassProperties = loadstring(HttpGet("https://raw.githubusercontent.com/frostyio/explorer/master/properties.lua"))();
  312. end
  313. end
  314. end
  315.  
  316. -- i should propably think of a better way to do this but im able to keep it basically automated with the run of a script
  317. local IconData;
  318.  
  319. if RunService:IsStudio() then
  320. IconData = require(ReplicatedStorage:WaitForChild("IconData"));
  321. else
  322. IconData = loadstring(HttpGet("https://raw.githubusercontent.com/frostyio/explorer/master/icon_data.lua"))();
  323. end
  324.  
  325. -- RectSize, RectOffset
  326.  
  327. -- MapId = "rbxasset://textures/ClassImages.png";
  328.  
  329. local function GetIconFromClass(Class)
  330. local Data = IconData[Class];
  331. -- why tf does sirthurt errorr here
  332. local RectSize = Vector2.new(Data[1][1], Data[1][2]);
  333. local RectOffset = Vector2.new(Data[2][1], Data[2][2]);
  334. return RectSize, RectOffset;
  335. end
  336.  
  337. -- misc functions --
  338.  
  339. local function SetZIndex(Frame, ZIndex)
  340. Frame.ZIndex = ZIndex;
  341. for _, object in pairs(Frame:GetDescendants()) do
  342. if object:IsA("GuiBase") then
  343. object.ZIndex = object.ZIndex + ZIndex;
  344. end
  345. end
  346. end
  347.  
  348. local function BringWindowToFront(Window)
  349. CurrentZIndexPriority = CurrentZIndexPriority + 5;
  350.  
  351. SetZIndex(Window, CurrentZIndexPriority);
  352. end
  353.  
  354. -- dragging --
  355. local drag;
  356. do
  357. local is_dragging, input_start, input_drag, position_start, item_drag, drag_frame, tween_time;
  358. local function update(input, gui)
  359. local delta = input.Position - input_start;
  360. local pos = UDim2.new(0, position_start.X.Offset + delta.X, 0, position_start.Y.Offset + delta.Y);
  361.  
  362. -- bounds --
  363. if drag_frame then
  364. local small_x = pos.X.Scale * gui.AbsoluteSize.X + pos.X.Offset;
  365. local small_y = pos.Y.Scale * gui.AbsoluteSize.Y + pos.Y.Offset;
  366.  
  367. local far_x = small_x + gui.Size.X.Offset;
  368. local far_y = small_y + gui.Size.Y.Offset;
  369.  
  370. local true_x = math.clamp(small_x, 0, drag_frame.AbsoluteSize.X - (far_x - small_x));
  371. local true_y = math.clamp(small_y, 0, drag_frame.AbsoluteSize.Y - (far_y - small_y));
  372.  
  373. pos = UDim2.new(0, true_x, 0, true_y);
  374. end
  375.  
  376. if tween_time then
  377. gui:TweenPosition(pos, 1, 1, tween_time, 1);
  378. else
  379. gui.Position = pos;
  380. end
  381. end
  382.  
  383. function drag(object, move_frame, tween, border_frame, update_func)
  384. move_frame = move_frame or object;
  385.  
  386. local connections = {};
  387.  
  388. table.insert(connections, object.InputBegan:Connect(function(input)
  389. if input.UserInputType == Enum.UserInputType.MouseButton1 then
  390. is_dragging = true;
  391. position_start = UDim2.new(0, move_frame.AbsolutePosition.X, 0, move_frame.AbsolutePosition.Y);
  392. input_start = input.Position;
  393. item_drag = move_frame;
  394. drag_frame = border_frame;
  395. tween_time = tween;
  396.  
  397. BringWindowToFront(move_frame);
  398.  
  399. if update_func then
  400. update_func(true);
  401. end
  402.  
  403. table.insert(connections, input.Changed:Connect(function()
  404. if input.UserInputState == Enum.UserInputState.End then
  405. is_dragging = false;
  406. if update_func then
  407. update_func(false);
  408. end
  409. end
  410. end))
  411.  
  412. end
  413. end))
  414.  
  415. table.insert(connections, object.InputChanged:Connect(function(input)
  416. if input.UserInputType == Enum.UserInputType.MouseMovement then
  417. input_drag = input;
  418. end
  419. end))
  420.  
  421. -- return --
  422. return {
  423. disconnect = function()
  424. for _, connection in pairs(connections) do connection:Disconnect() end;
  425. end
  426. }
  427. end
  428.  
  429. UserInputService.InputChanged:Connect(function(input)
  430. if input == input_drag and is_dragging then
  431. update(input, item_drag);
  432. end
  433. end);
  434. end
  435.  
  436.  
  437. -- Color Picker --
  438.  
  439. local ColorObject; do
  440. local function rgb_to_hsv(r, g, b)
  441. local max, min = math.max(r, g, b), math.min(r, g, b);
  442. local h, s, v;
  443. v = max;
  444.  
  445. local d = max - min;
  446. if max == 0 then s = 0 else s = d / max end;
  447. if max == min then
  448. h = 0; -- achromatic
  449. else
  450. if max == r then
  451. h = (g - b) / d ;
  452. if g < b then
  453. h = h + 6 ;
  454. end
  455. elseif max == g then
  456. h = (b - r) / d + 2;
  457. elseif max == b then
  458. h = (r - g) / d + 4;
  459. end
  460. h = h / 6;
  461. end
  462.  
  463. return h, s, v;
  464. end
  465.  
  466. local current_input, callback;
  467.  
  468. ColorObject = {
  469. h = nil,
  470. s = nil,
  471. v = nil,
  472.  
  473. new = function(this, frame, starting, cb)
  474. local self = setmetatable({}, this);
  475. self.Frame = frame:Clone();
  476. self.Frame.Parent = Gui;
  477. self.cb = cb;
  478. self.previous = starting;
  479.  
  480. self.h, self.s, self.v = rgb_to_hsv(starting.r, starting.g, starting.b);
  481. self:Update();
  482.  
  483. local Hue = self.Frame:WaitForChild("Hue");
  484. local Mask = self.Frame:WaitForChild("Mask");
  485. local ExitB = self.Frame:WaitForChild("Topbar"):WaitForChild("Exit");
  486.  
  487. ExitButton(ExitB);
  488.  
  489. ExitB.MouseButton1Click:Connect(function()
  490. self:cancel();
  491. end);
  492. self.Frame:WaitForChild("Cancel").MouseButton1Click:Connect(function() self:cancel(); end);
  493. self.Frame:WaitForChild("Ok").MouseButton1Click:Connect(function() self:hide(); end);
  494.  
  495. drag(self.Frame.Topbar, self.Frame);
  496. BringWindowToFront(self.Frame);
  497.  
  498. Mask.InputBegan:Connect(function(input)
  499. if input.UserInputType == Enum.UserInputType.MouseButton1 and not current_input then
  500. callback = function()
  501. self:SetMaskToMouse();
  502. self:Update();
  503. end;
  504.  
  505. local conn; conn = Mask.InputChanged:Connect(function(inp)
  506. if inp.UserInputType == Enum.UserInputType.MouseMovement then
  507. current_input = inp;
  508. end
  509. end);
  510.  
  511. local c; c = input.Changed:Connect(function()
  512. if input.UserInputState == Enum.UserInputState.End then
  513. current_input = nil;
  514. conn:Disconnect();
  515. c:Disconnect();
  516. end
  517. end);
  518. end
  519. end);
  520.  
  521. Hue.InputBegan:Connect(function(input)
  522. if input.UserInputType == Enum.UserInputType.MouseButton1 and not current_input then
  523. callback = function()
  524. self:SetHueToMouse();
  525. self:Update();
  526. end;
  527.  
  528. local conn; conn = Hue.InputChanged:Connect(function(inp)
  529. if inp.UserInputType == Enum.UserInputType.MouseMovement then
  530. current_input = inp;
  531. end
  532. end);
  533.  
  534. local c; c = input.Changed:Connect(function()
  535. if input.UserInputState == Enum.UserInputState.End then
  536. current_input = nil;
  537. conn:Disconnect();
  538. c:Disconnect();
  539. end
  540. end);
  541. end
  542. end);
  543.  
  544. return self;
  545. end,
  546. show = function(self)
  547. local Size = self.Frame.AbsoluteSize;
  548. self.Frame.Position = UDim2.new(0.5, -Size.X/2, 0.5, -Size.Y/2);
  549. self.Frame.Visible = true;
  550. self.previous = self.color;
  551. end,
  552. hide = function(self)
  553. self.Frame:Destroy();
  554. end,
  555. cancel = function(self)
  556. self.color = self.previous;
  557. self.cb(self.color);
  558. self:hide();
  559. end,
  560. SetMaskToMouse = function(self)
  561. local mask = self.Frame.Mask;
  562. local selector = mask.Frame;
  563. local abs = self.Frame.Mask.AbsolutePosition;
  564. local siz = self.Frame.Mask.AbsoluteSize;
  565. local siz2 = selector.AbsoluteSize;
  566. local mouse_pos = Vector2.new(Mouse.X, Mouse.Y);
  567. local delta = mouse_pos - abs;
  568. selector.Position = UDim2.new(
  569. 0, math.clamp(delta.X, siz2.X, siz.X - siz2.X),
  570. 0, math.clamp(delta.Y, siz2.Y, siz.Y - siz2.Y / 2)
  571. );
  572. self.v = math.clamp(1 - ((mouse_pos - abs).Y / mask.AbsoluteSize.Y), 0, 1);
  573. self.s = math.clamp(1 - ((mouse_pos - abs).X / mask.AbsoluteSize.X), 0, 1);
  574. end,
  575. SetHueToMouse = function(self)
  576. local selector = self.Frame.Hue.Frame;
  577. local abs = self.Frame.Hue.AbsolutePosition;
  578. local siz = self.Frame.Hue.AbsoluteSize;
  579. local siz2 = selector.AbsoluteSize;
  580. local mouse_pos = Vector2.new(Mouse.X, Mouse.Y);
  581. local delta = mouse_pos - abs;
  582. selector.Position = UDim2.new(
  583. 0, 0,
  584. 0, math.clamp(delta.Y, siz2.Y, siz.Y - siz2.Y / 2)
  585. );
  586. local a = math.clamp(((mouse_pos - abs).Y / siz.Y), 0, 1);
  587. self.h = a - (a*2) + 1;
  588. end,
  589. Update = function(self)
  590. self.Frame.Mask.ImageColor3 = Color3.fromHSV(self.h, 1, 1);
  591. self.color = Color3.fromHSV(self.h, self.s, self.v);
  592. self.cb(self.color);
  593. end
  594. };
  595. ColorObject.__index = ColorObject;
  596.  
  597. UserInputService.InputChanged:Connect(function(input)
  598. if input == current_input and callback then
  599. callback();
  600. end
  601. end);
  602. end
  603.  
  604. -- Notify --
  605.  
  606. local Notify; do
  607. local NotifyFrame = Gui:WaitForChild("Error"):Clone();
  608.  
  609. Notify = {
  610. new = function(this, title, info, width, height)
  611. local self = setmetatable({}, this);
  612.  
  613. local Frame = NotifyFrame:Clone();
  614.  
  615. local Topbar = Frame:WaitForChild("Topbar");
  616. local Exit = Topbar:WaitForChild("Exit");
  617. local Image = Frame:WaitForChild("ImageLabel");
  618. local Title = Image:WaitForChild("Title");
  619. local Info = Frame:WaitForChild("Info");
  620. local Ok = Frame:WaitForChild("Ok");
  621.  
  622. self.Frame = Frame;
  623.  
  624. local function Close() self:Close() end;
  625.  
  626. Exit.MouseButton1Click:Connect(Close);
  627. Ok.MouseButton1Click:Connect(Close);
  628.  
  629. Title.Text = title;
  630. Info.Text = info;
  631.  
  632. if width or height then
  633. Frame.Size = UDim2.new(width, 0, height, 0);
  634. end
  635. Frame.Visible = true;
  636. Frame.Parent = Gui;
  637.  
  638. drag(Topbar, Frame);
  639.  
  640. ExitButton(Exit);
  641. BringWindowToFront(Frame);
  642.  
  643. return self;
  644. end,
  645.  
  646. Close = function(self)
  647. self.Frame:Destroy();
  648. end
  649. };
  650. Notify.__index = Notify;
  651. end
  652.  
  653. -- misc --
  654.  
  655. function ExitButton(button)
  656. if button and (button:IsA("TextButton") or button:IsA("ImageButton")) then
  657. local CurrentTween = nil;
  658. local TweenTime = 0.3;
  659. local Property = button:IsA("TextButton") and "TextColor3" or "ImageColor3";
  660. local OriginalColor = button[Property];
  661.  
  662. local function CancelCurrentTween()
  663. if CurrentTween then
  664. CurrentTween:Cancel();
  665. CurrentTween = nil;
  666. end
  667. end
  668.  
  669. local function OnHover()
  670. CancelCurrentTween();
  671.  
  672. CurrentTween = TweenService:Create(button, TweenInfo.new(TweenTime), {[Property] = ExitRed});
  673. CurrentTween:Play();
  674. end
  675.  
  676. local function OnLeave()
  677. CancelCurrentTween();
  678.  
  679. CurrentTween = TweenService:Create(button, TweenInfo.new(TweenTime), {[Property] = OriginalColor});
  680. CurrentTween:Play();
  681. end
  682.  
  683. button.MouseEnter:Connect(OnHover);
  684. button.MouseLeave:Connect(OnLeave);
  685. end
  686. end
  687.  
  688. local function make_path(object)
  689. local parent, s = object, "";
  690. repeat
  691. local name = parent.Name;
  692. if name:match("[%a_]+") ~= name then name = "[\""..name.."\"]" else name = "." .. name end;
  693. s = ("%s"):format(name) .. s;
  694. parent = parent.Parent;
  695. until parent.Parent == game
  696. return (parent == workspace and "workspace" or ("game:GetService(\"%s\")"):format(parent.Name)) .. s;
  697. end
  698.  
  699. local function is_service(object)
  700. return game:GetService(object.ClassName) and true;
  701. end
  702.  
  703. local cached_decomp = {};
  704. local function decomp(obj)
  705. if decompile == nil then
  706. Notify:new("Decompiling error", "Please execute with an exploit that supports decompiling.");
  707. end
  708.  
  709. if cached_decomp[obj] then return cached_decomp[obj]; end;
  710. cached_decomp[obj] = decompile(obj);
  711. return cached_decomp[obj];
  712. end
  713.  
  714. local function sort_alphabetical(char, char2)
  715. assert(char:match("%a") and char2:match("%a") and #char + #char2 == 2, "invalid arguments");
  716. return char:lower():byte() < char2:lower():byte();
  717. end
  718.  
  719. local LastUpdate = 0;
  720.  
  721. local function TotalUpdate()
  722. if tick() - LastUpdate <= 0.1 then return end;
  723. LastUpdate = tick();
  724.  
  725. UpdateList(GetShowList());
  726. UpdateScrollbar();
  727. end
  728.  
  729. local function HideClickMenu()
  730. Dropdown.Visible = false;
  731. DropdownList:ClearAllChildren();
  732. end
  733.  
  734. -- right click menu lib --
  735.  
  736. local function AddHotkey(Name, Key, Func)
  737. if type(Key) ~= "table" then
  738. local NewFunc = function(...)
  739. local tbl = {};
  740. for object in pairs(Selection) do table.insert(tbl, object) end;
  741. if #tbl > 0 then
  742. Func(...);
  743. end
  744. return Enum.ContextActionResult.Pass
  745. end;
  746. ContextAction:BindAction(Name, NewFunc, false, Key);
  747. else
  748. local NumKeysDown = 0;
  749. local function NewFunc(name, state, obj)
  750. if state == Enum.UserInputState.Begin then
  751. NumKeysDown = NumKeysDown + 1;
  752. else
  753. NumKeysDown = NumKeysDown - 1;
  754. end
  755. if NumKeysDown == #Key then
  756. local tbl = {};
  757. for object in pairs(Selection) do table.insert(tbl, object) end;
  758. if #tbl > 0 then
  759. Func(name, state, obj);
  760. end
  761. end
  762. return Enum.ContextActionResult.Pass
  763. end
  764. ContextAction:BindAction(Name, NewFunc, false, unpack(Key));
  765. end
  766. end
  767. local function STL() -- SelectionToTable
  768. local tbl = {};for object in pairs(Selection) do table.insert(tbl, object) end return tbl;
  769. end;
  770.  
  771. local Last;
  772. local RightClickDropdown = {
  773. Button = function(self, Name, Icon, GrayedOut, func, Hotkey)
  774. local Clone = SlotTemplate:Clone();
  775. Clone.Parent = DropdownList;
  776. Clone.Position = UDim2.new(0, 0, 0, SlotSize.Y * (#DropdownList:GetChildren() - 1));
  777. Dropdown.Size = UDim2.new(0.65, 0, 0, SlotSize.Y * (#DropdownList:GetChildren()));
  778. Last = Clone;
  779. local Hover = Clone:WaitForChild("Hover");
  780. local Ic = Clone:WaitForChild("Icon");
  781. if Icon then
  782. Ic.ImageRectOffset = Vector2.new((Icon - 1) * 17, 0)
  783. else
  784. Ic.Visible = false;
  785. end
  786. Hover.MouseEnter:Connect(function()
  787. Hover.BackgroundTransparency = 0;
  788. end);
  789. Hover.MouseLeave:Connect(function()
  790. Hover.BackgroundTransparency = 1;
  791. end);
  792. if not GrayedOut then
  793. Hover.MouseButton1Click:Connect(function()
  794. if func then func() end;
  795. HideClickMenu();
  796. end)
  797. end
  798. local HotkeyLabel = Clone:WaitForChild("Hotkey");
  799. if Hotkey then
  800. HotkeyLabel.Text = Hotkey;
  801. HotkeyLabel.Visible = true;
  802. end
  803.  
  804. local Label = Clone:WaitForChild("Label");
  805. Label.Text = Name;
  806. if GrayedOut then
  807. Label.TextColor3 = Color3.fromRGB(127, 127, 127);
  808. HotkeyLabel.TextColor3 = Color3.fromRGB(127, 127, 127);
  809. end
  810. end,
  811. Divider = function(self)
  812. if Last then
  813. Last.Divider.Visible = true;
  814. end
  815. end
  816. }
  817.  
  818. -- right click menu click off --
  819.  
  820. local DropdownHovering = false;
  821.  
  822. Dropdown.InputBegan:Connect(function(input)
  823. if input.UserInputType == Enum.UserInputType.MouseMovement then
  824. DropdownHovering = true;
  825. end
  826. end);
  827. Dropdown.InputEnded:Connect(function(input)
  828. if input.UserInputType == Enum.UserInputType.MouseMovement then
  829. DropdownHovering = false;
  830. end
  831. end);
  832.  
  833. UserInputService.InputBegan:Connect(function(input)
  834. if input.UserInputType == Enum.UserInputType.MouseButton1 and not DropdownHovering then
  835. HideClickMenu();
  836. end
  837. end);
  838.  
  839.  
  840. -- this function was an after main production function which is why it isn't implemented as good as it could be
  841. local function GetChildrenShowing()
  842. if CustomChildrenShowing then
  843. return CustomChildrenShowing;
  844. end
  845. return ChildrenShowing;
  846. end
  847.  
  848. -- right click menu --
  849.  
  850. local function RightClickMenu()
  851. local Object;
  852. for object in pairs(Selection) do Object = object break end;
  853. if Object then
  854. -- general instance buttons --
  855. -- for some reason roblox just doesn't like you using control --
  856. RightClickDropdown:Button("Cut", 1, is_service(Object), function() clipboard = {Object:Clone()}; Object:Destroy(); end, "Shift+X");
  857. RightClickDropdown:Button("Copy", 2, is_service(Object), function() clipboard = {Object:Clone()}; end, "Shift+C");
  858. RightClickDropdown:Button("Paste Into", nil, clipboard == nil, function()
  859. for _, object in pairs(clipboard) do
  860. if typeof(object) == "Instance" then
  861. object:Clone().Parent = Object ;
  862. end
  863. end
  864. end, "Shift+Shift+V");
  865. RightClickDropdown:Button("Duplicate", 2, is_service(Object), function() Object:Clone().Parent = Object.Parent end, "Shift+D");
  866. RightClickDropdown:Button("Delete", 3, is_service(Object), function() Object:Destroy(); end, "Del");
  867. --RightClickDropdown:Button("Rename", nil, false, function() print("hi") end, "F2");
  868. RightClickDropdown:Divider();
  869. RightClickDropdown:Button("Group", 4, is_service(Object), function()
  870. local Model = Instance.new("Model");
  871. Model.Parent = Object.Parent;
  872. Object.Parent = Model;
  873. end, "Shift+G");
  874. RightClickDropdown:Button("Ungroup", 5, Object.ClassName ~= "Model", function()
  875. for _, object in pairs(Object:GetChildren()) do object.Parent = Object.Parent end;
  876. Object:Destroy();
  877. end, "Shift+U");
  878. RightClickDropdown:Button("Select Children", 6, false, function()
  879. GetChildrenShowing()[Object] = true;
  880. Selection[Object] = false;
  881. for _, obj in pairs(Object:GetChildren()) do Selection[obj] = obj SelectionBox.Adornee = obj; end;
  882. TotalUpdate();
  883. end);
  884. RightClickDropdown:Button("Teleport To", 7, not Object:IsA("BasePart"), function()
  885. if Client.Character then Client.Character:SetPrimaryPartCFrame(Object.CFrame) end;
  886. end, "F");
  887. RightClickDropdown:Divider();
  888. RightClickDropdown:Button("Insert Part", 8, false, function()
  889. Instance.new("Part").Parent = Object;
  890. end);
  891. RightClickDropdown:Button("Insert Object", nil, false, function() end);
  892. RightClickDropdown:Divider();
  893. RightClickDropdown:Button("Save Instance", nil, true, function() saveinstance(Object) end);
  894. RightClickDropdown:Button("Get Path", nil, false, function() setclipboard(make_path(Object)) end);
  895. RightClickDropdown:Divider();
  896.  
  897. -- script buttons --
  898. if Object:IsA("LocalScript") or Object:IsA("ModuleScript") then
  899. RightClickDropdown:Button("Save To Clipboard", 2, false, function()
  900. wrap(function() setclipboard(decomp(Object)) end)();
  901. end);
  902. RightClickDropdown:Button("Save To Workspace", nil, false, function()
  903. wrap(function() writefile(("%s.lua"):format(Object.Name), decomp(Object)) end)();
  904. end);
  905. RightClickDropdown:Button("View Script", 9, false, function()
  906. ScriptEditor:Show();
  907. wrap(function() ScriptEditor:CreateScript(Object.Name, decomp(Object)) end)();
  908. end);
  909. elseif Object:IsA("ClickDetector") then
  910. RightClickDropdown:Button("Fire click detector", nil, false, function()
  911. if fireclickdetector then
  912. fireclickdetector(Object);
  913. else
  914. Notify:new("Error", "Please execute with an exploit that supports fireclickdetector.");
  915. end
  916. end);
  917. end
  918. -- --;
  919.  
  920. Dropdown.Visible = true;
  921. Dropdown.Position = UDim2.new(0, Mouse.X - ExplorerFrame.AbsolutePosition.X + 5, 0, Mouse.Y - ExplorerFrame.AbsolutePosition.Y);
  922. end
  923. end
  924.  
  925. -- hotkeys
  926. do
  927. AddHotkey("Cut", {Enum.KeyCode.LeftShift, Enum.KeyCode.X}, function()
  928. local clip = {};
  929. for _, obj in pairs(STL()) do
  930. table.insert(clip, obj:Clone());
  931. obj:Destroy();
  932. end
  933. clipboard = clip;
  934. Selection = {};
  935. end);
  936. AddHotkey("Copy", {Enum.KeyCode.LeftShift, Enum.KeyCode.C}, function()
  937. clipboard = STL();
  938. end);
  939. AddHotkey("Paste Into", {Enum.KeyCode.LeftShift, Enum.KeyCode.V}, function()
  940. local Object = STL()[1];
  941. local new = {};
  942. for _, obj in pairs(clipboard) do
  943. local x = obj:Clone();
  944. new[x] = x;
  945. x.Parent = Object;
  946. end
  947. Selection = new;
  948. end);
  949. AddHotkey("Duplicate", {Enum.KeyCode.LeftShift, Enum.KeyCode.D}, function()
  950. local Object = STL()[1];
  951. local new = {};
  952. for _, obj in pairs(STL()) do
  953. local x = obj:Clone();
  954. new[x] = x;
  955. x.Parent = Object.Parent;
  956. end
  957. Selection = new;
  958. end);
  959. AddHotkey("Delete", Enum.KeyCode.Delete, function(Selection)
  960. for _, object in pairs(STL()) do object:Destroy() end;
  961. Selection = {};
  962. end);
  963. AddHotkey("Teleport To", Enum.KeyCode.F, function(Selection)
  964. local Object = STL()[1];
  965. if Object:IsA("BasePart") then
  966. if Client.Character and Client.Character.PrimaryPart then Client.Character:SetPrimaryPartCFrame(Object.CFrame) end;
  967. end
  968. end);
  969. end
  970.  
  971. -- explorer stuff --
  972.  
  973. local function GetFurthestOut() -- for HoverEnd
  974. local biggest = 0;
  975. for _, obj in pairs(ListObjects) do
  976. local title = obj.Label;
  977. local e = title.AbsolutePosition.X + title.TextBounds.X + 20 - Explorer.AbsolutePosition.X;
  978. if e > biggest then
  979. biggest = e;
  980. HoverEnd = e;
  981. end
  982. end
  983. end
  984.  
  985. local function UpdateSelections()
  986. for _, object in pairs(ListObjects) do
  987. object:UpdateSelect();
  988. end
  989. end
  990.  
  991. -- prefill the explorer list (only called once @Boot) with templates to use later on --
  992.  
  993. local function FillList()
  994. local Size = TemplateSize.Y;
  995. local Amount = math.floor(List.AbsoluteSize.Y / Size);
  996. for i = 1, Amount do
  997. local Object = ObjectTemplate:Clone();
  998. Object.Parent = List;
  999. Object.Position = UDim2.new(0, 0, 0, (i - 1) * Size);
  1000. Object.Name = ("Slot%d"):format(i);
  1001. local HitboxFrame = Object:WaitForChild("HitboxFrame");
  1002. local Hover = Object:WaitForChild("Hover");
  1003. local Selected = false;
  1004. local ObjectData = {
  1005. Label = Object:WaitForChild("Label"),
  1006. Icon = Object:WaitForChild("Icon"),
  1007. Dropdown = Object:WaitForChild("Dropdown"):WaitForChild("Dropdown"),
  1008. Frame = Object,
  1009. YPosition = (i - 1) * Size,
  1010. CurrentObject = nil,
  1011. UpdateHoverEnd = function(self)
  1012. local DistanceFrom0 = Object.AbsolutePosition.X - ExplorerFrame.AbsolutePosition.X;
  1013. Hover.Size = UDim2.new(0, HoverEnd - DistanceFrom0, 1.05, 0);
  1014. end,
  1015. Select = function(self)
  1016. if self.CurrentObject then
  1017. Selection[self.CurrentObject] = self.CurrentObject;
  1018. SelectionBox.Adornee = self.CurrentObject;
  1019. self:UpdateSelect();
  1020. Selected = true;
  1021. local Length = 0;
  1022. table.foreach(Selection, function() Length = Length + 1 end);
  1023. if Length == 1 then
  1024. LoadProperties(self.CurrentObject);
  1025. PropertyTitle.Text = ("Properties - %s \"%s\""):format(self.CurrentObject.ClassName, self.CurrentObject.Name);
  1026. else
  1027. PropertyTitle.Text = ("Properties - %d items"):format(Length);
  1028. end
  1029. end
  1030. UpdateSelections();
  1031. end,
  1032. UpdateSelect = function(self)
  1033. if Selection[self.CurrentObject] then
  1034. Hover.BackgroundColor3 = SelectionColor;
  1035. Hover.BackgroundTransparency = 0;
  1036. self.Label.TextColor3 = Color3.fromRGB(255, 255, 255);
  1037. Selected = true;
  1038. else
  1039. Hover.BackgroundColor3 = HoverColor;
  1040. Hover.BackgroundTransparency = 1;
  1041. self.Label.TextColor3 = TextColor;
  1042. Selected = false;
  1043. end
  1044. end,
  1045. };
  1046.  
  1047. ObjectData.Dropdown.Parent.MouseButton1Down:Connect(function()
  1048. if not ObjectData.CurrentObject then return end;
  1049. local ChildrenShowing = GetChildrenShowing();
  1050. if ChildrenShowing[ObjectData.CurrentObject] == nil then
  1051. ChildrenShowing[ObjectData.CurrentObject] = false;
  1052. end
  1053. ChildrenShowing[ObjectData.CurrentObject] = not ChildrenShowing[ObjectData.CurrentObject];
  1054. UpdateList(GetShowList());
  1055. UpdateScrollbar();
  1056. delay(1, function() UpdateList(GetShowList()) end);
  1057. for _, func in pairs(ChildAddedUpdates) do
  1058. func();
  1059. end
  1060. end);
  1061. Hover.MouseEnter:Connect(function()
  1062. if ObjectData.CurrentObject then
  1063. Hover.BackgroundTransparency = 0;
  1064. end
  1065. end);
  1066. Hover.MouseLeave:Connect(function()
  1067. if ObjectData.CurrentObject then
  1068. if Selected then return end;
  1069. Hover.BackgroundTransparency = 1;
  1070. end
  1071. end);
  1072. Hover.MouseButton1Click:Connect(function()
  1073. if not(ObjectData.CurrentObject) then return end;
  1074. if not UserInputService:IsKeyDown(Enum.KeyCode.LeftControl) then
  1075. Selection = {};
  1076. end
  1077. ObjectData:Select();
  1078. end);
  1079. Hover.MouseButton2Click:Connect(function()
  1080. if not(ObjectData.CurrentObject) then return end;
  1081. HideClickMenu();
  1082. Selection = {};
  1083. ObjectData:Select();
  1084. RightClickMenu();
  1085. end);
  1086.  
  1087. table.insert(ListObjects, ObjectData);
  1088. end
  1089. end
  1090.  
  1091. local function ChildrenLoop(object, list)
  1092. if GetChildrenShowing()[object] then
  1093. for _, obj in pairs(object:GetChildren()) do
  1094. if OnlyShow then
  1095. if OnlyShow[obj] then
  1096. table.insert(list, obj);
  1097. ChildrenLoop(obj, list);
  1098. end
  1099. else
  1100. table.insert(list, obj);
  1101. ChildrenLoop(obj, list);
  1102. end
  1103. end
  1104. end
  1105. end
  1106.  
  1107. function GetShowList()
  1108. if CustomShowList then
  1109. local ShowList = {};
  1110. for _, object in pairs(CustomShowList) do
  1111. if OnlyShow then
  1112. if OnlyShow[object] then
  1113. table.insert(ShowList, object);
  1114. ChildrenLoop(object, ShowList);
  1115. end
  1116. else
  1117. table.insert(ShowList, object);
  1118. ChildrenLoop(object, ShowList);
  1119. end
  1120. end
  1121. return ShowList
  1122. end
  1123.  
  1124. local ShowList = {};
  1125. for _, object in pairs(services) do
  1126. object = game:GetService(object);
  1127. table.insert(ShowList, object);
  1128. ChildrenLoop(object, ShowList);
  1129. end
  1130. return ShowList;
  1131. end
  1132.  
  1133. local PreviousConnections = {};
  1134.  
  1135. local function FindFirstChild(self, Object)
  1136. for _, obj in pairs(self:GetChildren()) do
  1137. if obj == Object then
  1138. return obj;
  1139. end
  1140. end
  1141. end
  1142.  
  1143. function UpdateList(ShowList)
  1144. local Indent = 0;
  1145. for _, connection in pairs(PreviousConnections) do connection:Disconnect() end;
  1146. PreviousConnections = {};
  1147.  
  1148. if Start > 1 then
  1149. for i = 1, Start - 1 do
  1150. local Object = ShowList[i];
  1151. if Object then
  1152. local NextObject = ShowList[i + 1];
  1153. if NextObject and FindFirstChild(Object, NextObject) then
  1154. Indent = Indent + 1;
  1155. else
  1156. -- INDENTATION FIX --
  1157. -- laggy on big games such as jailbreak --
  1158. -- therefor i disable it even though it is just a slight visual bug but saves frames! --
  1159. -- doesn't do much but it's worth it --
  1160.  
  1161. --if TotalObjects < 35000 then : ugh disabled cause it caused problems
  1162. local parent = Object;
  1163. while NextObject and NextObject.Parent ~= parent do
  1164. if parent == nil then break end;
  1165. parent = parent.Parent;
  1166. if NextObject.Parent ~= parent then
  1167. Indent = math.clamp(Indent - 1, 0, math.huge);
  1168. end
  1169. end
  1170. --end
  1171.  
  1172. end
  1173. end
  1174. end
  1175. end
  1176. for i = Start, Start + #ListObjects - 1 do
  1177. local Object = ShowList[i];
  1178. local ObjectFrame = ListObjects[i - Start + 1];
  1179. if Object then
  1180. ObjectFrame.Label.Text = Object.Name;
  1181. ObjectFrame.CurrentObject = Object;
  1182. ObjectFrame.Frame.Position = UDim2.new(0, Indent * 15, 0, ObjectFrame.YPosition);
  1183. ObjectFrame.Icon.Visible = true;
  1184. local Size, Offset = GetIconFromClass(Object.ClassName);
  1185. ObjectFrame.Icon.ImageRectOffset = Offset;
  1186. ObjectFrame.Icon.ImageRectSize = Size;
  1187.  
  1188. -- connections --
  1189.  
  1190. table.insert(PreviousConnections, Object:GetPropertyChangedSignal("Name"):Connect(function()
  1191. ObjectFrame.Label.Text = Object.Name;
  1192. end))
  1193. table.insert(PreviousConnections, Object.ChildRemoved:Connect(function()
  1194. UpdateList(GetShowList());
  1195. UpdateScrollbar();
  1196. end))
  1197. table.insert(PreviousConnections, Object.ChildAdded:Connect(function()
  1198. UpdateList(GetShowList());
  1199. UpdateScrollbar();
  1200. end))
  1201.  
  1202. -- --
  1203.  
  1204. local NextObject = ShowList[i + 1];
  1205. if NextObject and FindFirstChild(Object, NextObject) then
  1206. Indent = Indent + 1;
  1207. ObjectFrame.Dropdown.Visible = true;
  1208. ObjectFrame.Dropdown.Rotation = 0;
  1209. else
  1210. if #Object:GetChildren() > 0 then
  1211. ObjectFrame.Dropdown.Rotation = -90;
  1212. ObjectFrame.Dropdown.Visible = true;
  1213. else
  1214. ObjectFrame.Dropdown.Visible = false;
  1215. end
  1216. local parent = Object;
  1217. while NextObject and NextObject.Parent ~= parent do
  1218. if parent == nil then break end;
  1219. parent = parent.Parent;
  1220. if NextObject.Parent ~= parent then
  1221. Indent = math.clamp(Indent - 1, 0, math.huge);
  1222. end
  1223. end
  1224. end
  1225. else
  1226. ObjectFrame.Label.Text = "";
  1227. ObjectFrame.Dropdown.Visible = false;
  1228. ObjectFrame.Icon.Visible = false;
  1229. ObjectFrame.CurrentObject = nil;
  1230. end
  1231. end
  1232. end
  1233.  
  1234. local function ShowChildrenTilWorkspace(Childrenshowing, Onlyshowing, object)
  1235. local parent = object;
  1236.  
  1237. repeat
  1238. Childrenshowing[parent] = true;
  1239. Onlyshowing[parent] = true;
  1240. parent = parent.Parent
  1241. until parent == workspace or parent == game;
  1242. end
  1243.  
  1244. -- i really gotta do something about how ugly this is
  1245. local function CustomExplorerList(List, ChildrenShowing, OnlySh)
  1246. CustomShowList = List;
  1247. OnlyShow = OnlySh;
  1248. CustomChildrenShowing = ChildrenShowing;
  1249.  
  1250. TotalUpdate();
  1251. UpdateSelections();
  1252. end
  1253.  
  1254. local function ShowDataModel()
  1255. CustomShowList = nil;
  1256. CustomChildrenShowing = nil;
  1257. OnlyShow = nil;
  1258.  
  1259. for _, object in pairs(Selection) do
  1260. ShowChildrenTilWorkspace(ChildrenShowing, {}, object);
  1261. end
  1262.  
  1263. TotalUpdate();
  1264. UpdateSelections();
  1265. end
  1266.  
  1267. local function ViewOnExplorer(object)
  1268. local index = nil;
  1269. for i, obj in pairs(GetShowList()) do
  1270. if obj == object then
  1271. index = i;
  1272. break;
  1273. end
  1274. end
  1275.  
  1276. if index then
  1277. Start = index;
  1278. TotalUpdate();
  1279. UpdateSelections();
  1280. end
  1281. end
  1282.  
  1283. local charset = {};
  1284. for i = 48, 57 do table.insert(charset, string.char(i)) end;
  1285. for i = 65, 90 do table.insert(charset, string.char(i)) end;
  1286. for i = 97, 122 do table.insert(charset, string.char(i)) end;
  1287.  
  1288. local function RandomString(length)
  1289. local str = "";
  1290. for i = 1, length do
  1291. str = str .. charset[Random.new():NextInteger(1, #charset)];
  1292. end
  1293. return str;
  1294. end
  1295.  
  1296. -- my semi fix for the comment @ the line above CustomExplorerList
  1297.  
  1298. local function DirectShow(obs)
  1299. -- only works with Workspace rn
  1300.  
  1301. local Objects = {workspace};
  1302. local Childrenshowing = {[workspace] = true};
  1303. local Onlyshowing = {[workspace] = true};
  1304.  
  1305. for _, object in pairs(obs) do
  1306. ShowChildrenTilWorkspace(Childrenshowing, Onlyshowing, object);
  1307. end
  1308.  
  1309. CustomExplorerList(Objects, Childrenshowing, Onlyshowing);
  1310. end
  1311.  
  1312. UserInputService.InputBegan:Connect(function(input, gpe)
  1313. if input.UserInputType == Enum.UserInputType.MouseButton3 then
  1314. local Selected;
  1315. for _, obj in pairs(Selection) do Selected = obj break end;
  1316. if Selected then
  1317. ViewOnExplorer(Selected);
  1318. end
  1319. elseif input.UserInputType == Enum.UserInputType.MouseButton1 and UserInputService:IsKeyDown(Enum.KeyCode.LeftAlt) then
  1320. local target = Mouse.Target;
  1321. if target then
  1322. ViewOnExplorer(target);
  1323. Selection = {};
  1324. Selection[target] = true;
  1325. UpdateSelections();
  1326. end
  1327. end
  1328. end);
  1329.  
  1330. -- Scrollbar --
  1331.  
  1332. do
  1333. -- looking back on this, this is still very ugly code that im too laze to improve --
  1334. local function GetScrollPercent(ListObjects)
  1335. return (Start - 1) / (#ListObjects - 3);
  1336. end
  1337.  
  1338. local Button = Zone:WaitForChild("Button");
  1339.  
  1340. function UpdateScrollbar()
  1341. local List = GetShowList();
  1342. local Num = #List;
  1343.  
  1344. local GoesOverBy = Num - #ListObjects;
  1345. ScrollButton.Position = UDim2.new(0, 0, GetScrollPercent(List), 0);
  1346. local IterateAmount = 1;
  1347. for _, func in pairs(ScrollUpdates) do func() end;
  1348.  
  1349. local ViewportRatio = Zone.AbsoluteSize.Y / (Num * TemplateSize.Y);
  1350. if ViewportRatio < 1 then
  1351. Scrollbar.Visible = true;
  1352. Button.Size = UDim2.new(1, 0, 0, Zone.AbsoluteSize.Y * ViewportRatio);
  1353. else
  1354. Scrollbar.Visible = false;
  1355. Start = 1;
  1356. UpdateList(GetShowList());
  1357. end
  1358. end
  1359.  
  1360. local YDelta = 0;
  1361. local function StartScroll()
  1362. RunService:BindToRenderStep("Scrollbar", 1, function()
  1363. local List = GetShowList();
  1364. local Percentage = math.clamp((Mouse.Y - Zone.AbsolutePosition.Y) / Zone.AbsoluteSize.Y, 0, 1);
  1365. ScrollButton.Position = UDim2.new(0, 0, Percentage, -YDelta);
  1366. Start = math.floor(Percentage * (#List - #ListObjects)) + 1;
  1367. UpdateList(List);
  1368. UpdateScrollbar();
  1369. end);
  1370. end
  1371. local function EndScroll()
  1372. RunService:UnbindFromRenderStep("Scrollbar");
  1373. end
  1374.  
  1375. UpArrow.MouseButton1Down:Connect(function()
  1376. Start = math.clamp(Start - 1, 1, math.huge);
  1377. UpdateList(GetShowList());
  1378. UpdateScrollbar();
  1379. end);
  1380. DownArrow.MouseButton1Down:Connect(function()
  1381. local ShowList = GetShowList();
  1382. Start = math.clamp(Start + 1, 1, math.clamp(#ShowList - #ListObjects + 1, 1, math.huge));
  1383. UpdateList(ShowList)
  1384. UpdateScrollbar();
  1385. end);
  1386.  
  1387. ScrollButton.InputBegan:Connect(function(input)
  1388. if input.UserInputType == Enum.UserInputType.MouseButton1 then
  1389. StartScroll();
  1390. YDelta = Mouse.Y - ScrollButton.AbsolutePosition.Y;
  1391. input.Changed:Connect(function()
  1392. if input.UserInputState == Enum.UserInputState.End then
  1393. EndScroll();
  1394. end
  1395. end);
  1396. end
  1397. end);
  1398. local LastMaxZoom, LastMinZoom;
  1399. Explorer.InputBegan:Connect(function(input)
  1400. if input.UserInputType == Enum.UserInputType.MouseMovement then
  1401. ExplorerHovering = true;
  1402. LastMaxZoom = Client.CameraMaxZoomDistance;
  1403. LastMinZoom = Client.CameraMinZoomDistance;
  1404. local Head = (Client.Character or Client.CharacterAdded:Wait()):WaitForChild("Head");
  1405. local Zoom = (workspace.CurrentCamera.CoordinateFrame.p - Head.Position).Magnitude;
  1406. Client.CameraMaxZoomDistance = Zoom;
  1407. Client.CameraMinZoomDistance = Zoom;
  1408. end
  1409. end);
  1410. Explorer.InputChanged:Connect(function(input)
  1411. if input.UserInputType == Enum.UserInputType.MouseWheel and ExplorerHovering then
  1412. if input.Position.Z == 1 then
  1413. Start = math.clamp(Start - 2, 1, math.huge);
  1414. UpdateList(GetShowList());
  1415. UpdateScrollbar();
  1416. else
  1417. local ShowList = GetShowList();
  1418. Start = math.clamp(Start + 2, 1, math.clamp(#ShowList - #ListObjects + 2, 1, math.huge));
  1419. UpdateList(ShowList)
  1420. UpdateScrollbar();
  1421. end
  1422. end
  1423. end);
  1424. Explorer.InputEnded:Connect(function(input)
  1425. if input.UserInputType == Enum.UserInputType.MouseMovement then
  1426. ExplorerHovering = false;
  1427. Client.CameraMaxZoomDistance = LastMaxZoom;
  1428. Client.CameraMinZoomDistance = LastMinZoom;
  1429. end
  1430. end);
  1431.  
  1432. -- our filter workspace!!
  1433.  
  1434. local function FindInWorkspace(Data)
  1435. local RetData = {};
  1436.  
  1437. Data = Data:lower();
  1438.  
  1439. for _, obj in pairs(workspace:GetDescendants()) do
  1440. if obj.ClassName:lower():match(Data) then
  1441. table.insert(RetData, obj);
  1442. elseif obj.Name:lower():match(Data) then
  1443. table.insert(RetData, obj);
  1444. end
  1445. end
  1446.  
  1447. return RetData;
  1448. end
  1449.  
  1450. FilterInput.FocusLost:Connect(function(Enter)
  1451. if not Enter then return end;
  1452.  
  1453. local Text = FilterInput.Text;
  1454. if #Text == 0 then
  1455. ShowDataModel();
  1456. return;
  1457. end
  1458.  
  1459. local a = tick();
  1460. local Data = FindInWorkspace(FilterInput.Text);
  1461. DirectShow(Data);
  1462. end);
  1463.  
  1464. -- exit
  1465.  
  1466. ExplorerExitButton.MouseButton1Click:Connect(function()
  1467. Gui:Destroy();
  1468. script:Destroy();
  1469. end);
  1470.  
  1471. ExitButton(ExplorerExitButton);
  1472. end
  1473.  
  1474. -- Properties
  1475.  
  1476. do
  1477. local PropertyScroll = Properties:WaitForChild("Scrollbar");
  1478. local DownArrow = PropertyScroll:WaitForChild("DownArrow");
  1479. local UpArrow = PropertyScroll:WaitForChild("UpArrow");
  1480. local Zone = PropertyScroll:WaitForChild("Zone");
  1481. local ScrollButton = Zone:WaitForChild("Button");
  1482.  
  1483. local ListObjects, ShowList, Categories, Connections = {}, {}, {}, {};
  1484. local Start = 1;
  1485. local UpdateList, UpdateShowList;
  1486. local CurrentLoaded;
  1487.  
  1488. local function GetScrollPercent(ListObjects)
  1489. return (Start - 1) / (#ListObjects - 3);
  1490. end
  1491.  
  1492. local function UpdateScrollbar()
  1493. local List = ShowList;
  1494. local Num = #List;
  1495.  
  1496. local GoesOverBy = Num - #ListObjects;
  1497. ScrollButton.Position = UDim2.new(0, 0, GetScrollPercent(List), 0);
  1498. --for _, func in pairs(ScrollUpdates) do func() end;
  1499.  
  1500. local ViewportRatio = Zone.AbsoluteSize.Y / (Num * PropertySize.Y);
  1501. if ViewportRatio < 1 then
  1502. PropertyScroll.Visible = true;
  1503. ScrollButton.Size = UDim2.new(1, 0, 0, Zone.AbsoluteSize.Y * ViewportRatio);
  1504. else
  1505. PropertyScroll.Visible = false;
  1506. Start = 1;
  1507. UpdateList(ShowList);
  1508. end
  1509. end
  1510.  
  1511. local YDelta = 0;
  1512. local function StartScroll()
  1513. RunService:BindToRenderStep("Scrollbar", 1, function()
  1514. local List = ShowList;
  1515. local Percentage = math.clamp((Mouse.Y - Zone.AbsolutePosition.Y) / Zone.AbsoluteSize.Y, 0, 1);
  1516. ScrollButton.Position = UDim2.new(0, 0, Percentage, -YDelta);
  1517. Start = math.floor(Percentage * (#List - #ListObjects)) + 1;
  1518. UpdateList(List);
  1519. UpdateScrollbar();
  1520. end);
  1521. end
  1522. local function EndScroll()
  1523. RunService:UnbindFromRenderStep("Scrollbar");
  1524. end
  1525.  
  1526. UpArrow.MouseButton1Down:Connect(function()
  1527. Start = math.clamp(Start - 1, 1, math.huge);
  1528. UpdateList(ShowList);
  1529. UpdateScrollbar();
  1530. end);
  1531. DownArrow.MouseButton1Down:Connect(function()
  1532. Start = math.clamp(Start + 1, 1, math.clamp(#ShowList - #ListObjects + 1, 1, math.huge));
  1533. UpdateList(ShowList)
  1534. UpdateScrollbar();
  1535. end);
  1536.  
  1537. ScrollButton.InputBegan:Connect(function(input)
  1538. if input.UserInputType == Enum.UserInputType.MouseButton1 then
  1539. StartScroll();
  1540. YDelta = Mouse.Y - ScrollButton.AbsolutePosition.Y;
  1541. input.Changed:Connect(function()
  1542. if input.UserInputState == Enum.UserInputState.End then
  1543. EndScroll();
  1544. end
  1545. end);
  1546. end
  1547. end);
  1548. local LastMaxZoom, LastMinZoom;
  1549. Properties.InputBegan:Connect(function(input)
  1550. if input.UserInputType == Enum.UserInputType.MouseMovement then
  1551. PropertiesHovering = true;
  1552. LastMaxZoom = Client.CameraMaxZoomDistance;
  1553. LastMinZoom = Client.CameraMinZoomDistance;
  1554. local Head = (Client.Character or Client.CharacterAdded:Wait()):WaitForChild("Head");
  1555. local Zoom = (workspace.CurrentCamera.CoordinateFrame.p - Head.Position).Magnitude;
  1556. Client.CameraMaxZoomDistance = Zoom;
  1557. Client.CameraMinZoomDistance = Zoom;
  1558. end
  1559. end);
  1560. Properties.InputChanged:Connect(function(input)
  1561. if input.UserInputType == Enum.UserInputType.MouseWheel and PropertiesHovering then
  1562. if input.Position.Z == 1 then
  1563. Start = math.clamp(Start - 2, 1, math.huge);
  1564. UpdateList(ShowList);
  1565. UpdateScrollbar();
  1566. else
  1567. Start = math.clamp(Start + 2, 1, math.clamp(#ShowList - #ListObjects + 4, 1, math.huge));
  1568. UpdateList(ShowList)
  1569. UpdateScrollbar();
  1570. end
  1571. end
  1572. end);
  1573. Properties.InputEnded:Connect(function(input)
  1574. if input.UserInputType == Enum.UserInputType.MouseMovement then
  1575. PropertiesHovering = false;
  1576. Client.CameraMaxZoomDistance = LastMaxZoom;
  1577. Client.CameraMinZoomDistance = LastMinZoom;
  1578. end
  1579. end);
  1580.  
  1581. local function FillList()
  1582. local Size = PropertySize.Y;
  1583. local Amount = math.floor(List.AbsoluteSize.Y / Size);
  1584. for i = 1, Amount do
  1585. local Object = PropertyTemplate:Clone();
  1586. Object.Parent = PropertiesList;
  1587. Object.Position = UDim2.new(0, 0, 0, (i - 1) * Size);
  1588. Object.Name = ("Slot%d"):format(i);
  1589. local ObjectData = {
  1590. Frame = Object,
  1591. YPosition = (i - 1) * Size,
  1592. CurrentObject = nil,
  1593.  
  1594. TextInput = nil,
  1595. ButtonClick = nil
  1596. };
  1597.  
  1598. local Dropdown = Object.Category.Dropdown;
  1599. ObjectData.Dropdown = Dropdown;
  1600. ObjectData.Divider = Object.Divider;
  1601.  
  1602. -- this is for when the strings get randomized
  1603. do -- string
  1604. local frame = Object:WaitForChild("string");
  1605. local label = frame:WaitForChild("Label");
  1606. local Box = frame:WaitForChild("Box");
  1607. local hover = frame:WaitForChild("Hover");
  1608. ObjectData["string"] = {Frame = frame, Label = label, Box = Box, Hover = hover};
  1609. end;
  1610. do -- category
  1611. local frame = Object:WaitForChild("Category");
  1612. local label = frame:WaitForChild("Label");
  1613. local Hover = frame:WaitForChild("Hover");
  1614. local Dropdown = frame:WaitForChild("Dropdown");
  1615. local HitboxFrame = frame:WaitForChild("HitboxFrame");
  1616. local Style = frame:WaitForChild("Style");
  1617. ObjectData["Category"] = {Frame = frame, Label = label, HitboxFrame = HitboxFrame, Hover = Hover,
  1618. Dropdown = Dropdown, Style = Style};
  1619. end;
  1620. do -- bool
  1621. local frame = Object:WaitForChild("bool");
  1622. local label = frame:WaitForChild("Label");
  1623. local Hover = frame:WaitForChild("Hover");
  1624. local Check = frame:WaitForChild("Check");
  1625. local Mark = Check:WaitForChild("Frame"):WaitForChild("Mark");
  1626. ObjectData["bool"] = {Frame = frame, Label = label, Check = Check, Hover = Hover, Mark = Mark};
  1627. end;
  1628. do -- int
  1629. local frame = Object:WaitForChild("int");
  1630. local label = frame:WaitForChild("Label");
  1631. local Hover = frame:WaitForChild("Hover");
  1632. local Box = frame:WaitForChild("Box");
  1633. ObjectData["int"] = {Frame = frame, Label = label, Box = Box, Hover = hover};
  1634. end;
  1635. do -- float
  1636. local frame = Object:WaitForChild("float");
  1637. local label = frame:WaitForChild("Label");
  1638. local Hover = frame:WaitForChild("Hover");
  1639. local Box = frame:WaitForChild("Box");
  1640. ObjectData["float"] = {Frame = frame, Label = label, Box = Box, Hover = hover};
  1641. end;
  1642. do -- Color3
  1643. local frame = Object:WaitForChild("Color3");
  1644. local label = frame:WaitForChild("Label");
  1645. local Hover = frame:WaitForChild("Hover");
  1646. local Box = frame:WaitForChild("Box");
  1647. local Click = frame:WaitForChild("Click");
  1648. ObjectData["Color3"] = {Frame = frame, Label = label, Box = Box, Hover = hover, Click = Click};
  1649. end;
  1650.  
  1651. ObjectData.Dropdown.MouseButton1Down:Connect(function()
  1652. if not ObjectData.CurrentObject then return end;
  1653. ObjectData.CurrentObject.DropdownOpened = not ObjectData.CurrentObject.DropdownOpened;
  1654. if not ObjectData.CurrentObject.DropdownOpened then
  1655. ObjectData.Dropdown.Rotation = -90;
  1656. else
  1657. ObjectData.Dropdown.Rotation = 0;
  1658. end
  1659. UpdateShowList();
  1660. UpdateList(ShowList)
  1661. end);
  1662.  
  1663. -- event types (Object, EventArguments) :
  1664. -- TextInput : Textbox.FocusLost
  1665. -- ButtonClick : TextButton.MouseButton1Click
  1666. -- ButtonHover (bool hovering) : TextButton.MouseEnter/TextButton.MouseLeave
  1667.  
  1668. -- connecting up connections --
  1669.  
  1670. for _, obj in pairs(Object:GetDescendants()) do
  1671. if obj:IsA("TextBox") then
  1672. obj.FocusLost:Connect(function(...)
  1673. if ObjectData.TextInput then
  1674. ObjectData.TextInput(obj, ...);
  1675. end
  1676. end);
  1677. elseif obj:IsA("TextButton") or obj:IsA("ImageButton") then
  1678. obj.MouseButton1Down:Connect(function(...)
  1679. if ObjectData.ButtonClick then
  1680. ObjectData.ButtonClick(obj, ...);
  1681. end
  1682. end);
  1683. obj.MouseEnter:Connect(function()
  1684. if ObjectData.ButtonHover then
  1685. ObjectData.ButtonHover(obj, true);
  1686. end
  1687. end);
  1688. obj.MouseLeave:Connect(function()
  1689. if ObjectData.ButtonHover then
  1690. ObjectData.ButtonHover(obj, false);
  1691. end
  1692. end);
  1693. end
  1694. end
  1695.  
  1696. -- ok --
  1697.  
  1698. table.insert(ListObjects, ObjectData);
  1699. end
  1700. end
  1701.  
  1702. function UpdateList(ShowList)
  1703. -- Need to change so everything isn't being indexed by name and rather by a reference w/ Name Randomization
  1704. for i = Start, Start + #ListObjects - 1 do
  1705. local Object = ShowList[i];
  1706. local ObjectFrame = ListObjects[i - Start + 1];
  1707. -- ObjectFrame = ObjectData
  1708. -- Object = Property
  1709. if Object then
  1710. ObjectFrame.CurrentObject = Object;
  1711. for _, child in pairs(ObjectFrame.Frame:GetChildren()) do
  1712. child.Visible = false;
  1713. end
  1714. local ValueType = Object.ValueType;
  1715. local Frame = ObjectFrame.Frame;
  1716.  
  1717. --local ValueFrame = Frame:FindFirstChild(ValueType);
  1718. local ValueFrame = ObjectFrame[ValueType];
  1719.  
  1720. if not ObjectFrame.CurrentObject.DropdownOpened then
  1721. ObjectFrame.Dropdown.Rotation = -90;
  1722. else
  1723. ObjectFrame.Dropdown.Rotation = 0;
  1724. end
  1725. if ValueFrame then
  1726. ValueFrame.Label.Text = Object.Name;
  1727. ValueFrame.Frame.Visible = true;
  1728. ObjectFrame.Divider.Visible = true;
  1729.  
  1730. if Object.ReadOnly then
  1731. ValueFrame.Label.TextColor3 = ReadOnlyColor;
  1732. else
  1733. ValueFrame.Label.TextColor3 = TextColor;
  1734. end
  1735.  
  1736. -- TODO --
  1737. -- this is the part where you control the properties such as changing them and showing them! --
  1738. -- add all roblox datatypes and not just have string and boolean --
  1739.  
  1740. if ValueType == "string" then
  1741. ValueFrame.Box.Text = tostring(Object.Value);
  1742. if Object.ReadOnly then
  1743. ValueFrame.Box.TextColor3 = ReadOnlyColor;
  1744. ValueFrame.Box.TextEditable = false;
  1745. else
  1746. ValueFrame.Box.TextColor3 = TextColor;
  1747. ValueFrame.Box.TextEditable = true;
  1748. ObjectFrame.TextInput = function(object)
  1749. if object == ValueFrame.Box then
  1750. CurrentLoaded[Object.Name] = ValueFrame.Box.Text;
  1751. end
  1752. end
  1753. end
  1754. elseif ValueType == "bool" then
  1755. if Object.Value then
  1756. ValueFrame.Mark.Visible = true;
  1757. else
  1758. ValueFrame.Mark.Visible = false;
  1759. end
  1760. if Object.ReadOnly then
  1761. ValueFrame.Mark.ImageColor3 = ReadOnlyColor;
  1762. ValueFrame.Mark.Parent.BackgroundColor3 = Color3.fromRGB(80, 80, 80);
  1763. else
  1764. ValueFrame.Mark.ImageColor3 = CheckmarkBlue;
  1765. ValueFrame.Mark.Parent.BackgroundColor3 = CheckmarkBackground;
  1766. ObjectFrame.ButtonClick = function(object)
  1767. if object == ValueFrame.Check then
  1768. CurrentLoaded[Object.Name] = not CurrentLoaded[Object.Name];
  1769. ValueFrame.Mark.Visible = CurrentLoaded[Object.Name];
  1770. end
  1771. end
  1772. end
  1773. elseif ValueType == "int" or ValueType == "float" then
  1774. ValueFrame.Box.Text = tostring(("%.03f"):format(Object.Value));
  1775. if Object.ReadOnly then
  1776. ValueFrame.Box.TextColor3 = ReadOnlyColor;
  1777. ValueFrame.Box.TextEditable = false;
  1778. else
  1779. ValueFrame.Box.TextColor3 = TextColor;
  1780. ValueFrame.Box.TextEditable = true;
  1781. ObjectFrame.TextInput = function(object)
  1782. if object == ValueFrame.Box then
  1783. CurrentLoaded[Object.Name] = tonumber(ValueFrame.Box.Text);
  1784. end
  1785. end
  1786. end
  1787. elseif ValueType == "Color3" then
  1788. local a = Object.Value;
  1789. ValueFrame.Box.Text = ("[Color] %d, %d, %d"):format(a.r * 255, a.g * 255, a.b * 255);
  1790. if Object.ReadOnly then
  1791. ValueFrame.Box.TextColor3 = ReadOnlyColor;
  1792. else
  1793. ValueFrame.Box.TextColor3 = TextColor;
  1794. ObjectFrame.ButtonClick = function(object)
  1795. if object == ValueFrame.Click then
  1796. ColorObject:new(TemplateFrame, a, function(color)
  1797. CurrentLoaded[Object.Name] = color;
  1798. end):show();
  1799. end
  1800. end
  1801. end
  1802. end
  1803. end
  1804. else
  1805. for _, child in pairs(ObjectFrame.Frame:GetChildren()) do
  1806. child.Visible = false;
  1807. end
  1808. end
  1809. end
  1810. end
  1811.  
  1812. local function DropdownLoop(Data, ShowList)
  1813. if Data.DropdownOpened then
  1814. for _, property in pairs(Data.Dropdown) do
  1815. if PropertyTemplate:FindFirstChild(property.ValueType) then
  1816. property.Value = CurrentLoaded[property.Name];
  1817. table.insert(ShowList, property);
  1818. DropdownLoop(property, ShowList);
  1819. else
  1820. --warn(("Unsupported data type %s, making string"):format(property.ValueType));
  1821. property.ValueType = "string";
  1822. property.Value = tostring(property.Value);
  1823. table.insert(ShowList, property);
  1824. DropdownLoop(property, ShowList);
  1825. end
  1826. end
  1827. end
  1828. end
  1829. function UpdateShowList()
  1830. local new = {}
  1831. for _, data in pairs(ShowList) do
  1832. if data.ValueType == "Category" then
  1833. table.insert(new, data);
  1834. DropdownLoop(data, new);
  1835. end
  1836. end
  1837. ShowList = new;
  1838. end
  1839.  
  1840. function LoadProperties(Object)
  1841. if CurrentLoaded == Object then return end;
  1842. for _, connection in pairs(Connections) do connection:Disconnect() end;
  1843. UpdateScrollbar();
  1844. Connections = {};
  1845. CurrentLoaded = Object;
  1846. local Data = ClassProperties[Object.ClassName];
  1847. local Properties = Data.Properties;
  1848. Categories = {};
  1849. for name, property in pairs(Properties) do
  1850. local category = property.Category;
  1851. if Categories[category] == nil then
  1852. Categories[category] = {};
  1853. end
  1854. local list = Categories[category];
  1855. local s, v = pcall(function() return Object[name] end);
  1856. if s and property.Deprecated ~= true then
  1857. table.insert(list, {
  1858. Value = Object[name],
  1859. Name = name,
  1860. DropdownOpened = false,
  1861. -- eventually will make it so you can like dropdown on XYZ and get individual number slots for each one like the
  1862. -- real explorer
  1863. Dropdown = {
  1864. -- {"Number", 50, print}
  1865. },
  1866. ValueType = property.ValueType,
  1867. ReadOnly = property.ReadOnly,
  1868. Deprecated = property.Deprecated
  1869. });
  1870. end
  1871. end
  1872.  
  1873. local NewCategories = {};
  1874. for category, properties in pairs(Categories) do
  1875. table.insert(NewCategories, {category, properties});
  1876. end
  1877.  
  1878.  
  1879. -- this isn't techincally mimicing the real explorer as the real explorer only sorts into alphabetical order
  1880. -- for the categories then for the properties but oh well
  1881. table.sort(NewCategories, function(a, b)
  1882. return sort_alphabetical(a[1]:sub(1,1), b[1]:sub(1,1));
  1883. end)
  1884.  
  1885. ShowList = {};
  1886. for _, data in pairs(NewCategories) do
  1887. local category, properties = unpack(data);
  1888. local Data = {
  1889. Value = nil,
  1890. Name = category,
  1891. DropdownOpened = true,
  1892. Dropdown = properties,
  1893. ValueType = "Category",
  1894. };
  1895. table.insert(ShowList, Data);
  1896. DropdownLoop(Data, ShowList);
  1897. end
  1898.  
  1899. UpdateList(ShowList);
  1900. end
  1901.  
  1902. FillList()
  1903. end
  1904.  
  1905. -- script viewer
  1906.  
  1907. do
  1908.  
  1909. local CodeReview = Gui:WaitForChild("CodeReview");
  1910. local Code = CodeReview:WaitForChild("Code");
  1911. local HorizontalOutline = CodeReview:WaitForChild("HorizontalOutline");
  1912. local VerticalOutline = CodeReview:WaitForChild("VerticalOutline");
  1913. local EditorFrame = Code:WaitForChild("Editor");
  1914. local LineNumbers = Code:WaitForChild("LineNumbers");
  1915. local TabList = CodeReview:WaitForChild("TabList");
  1916. local TabFrame = TabList:WaitForChild("Frame");
  1917. local TabTemplate = TabFrame:WaitForChild("Template");
  1918. local Ribbon = CodeReview:WaitForChild("Ribbon");
  1919. local Clipboard = Ribbon:WaitForChild("Clipboard");
  1920. local Folder = Ribbon:WaitForChild("Folder");
  1921. local Exit = Ribbon:WaitForChild("Exit");
  1922. local Title = Ribbon:WaitForChild("Title");
  1923. local Finder = CodeReview:WaitForChild("Finder");
  1924. local FinderInput = Finder:WaitForChild("Input");
  1925. local Matches = Finder:WaitForChild("Matches");
  1926. local UpArrow = Finder:WaitForChild("UpArrow");
  1927. local DownArrow = Finder:WaitForChild("DownArrow");
  1928. local FinderExit = Finder:WaitForChild("Exit");
  1929. local Template = TabTemplate:Clone(); TabTemplate:Destroy();
  1930.  
  1931. do
  1932.  
  1933. local Lexer;
  1934. -- lost my own lexer and too lazy to recreate, using a modified penlight lexer as it's fast and already made
  1935. if RunService:IsStudio() then
  1936. Lexer = require(ReplicatedStorage.Lexer).scan;
  1937. else
  1938. local String = game:HttpGet("https://pastebin.com/raw/1FkZFmhb");
  1939. Lexer = loadstring(String)().scan;
  1940. end
  1941.  
  1942. local TabSelectionColor = Color3.fromRGB(37, 37, 37);
  1943. local TabColor = Color3.fromRGB(53, 53, 53);
  1944. local CurrentScript = nil;
  1945.  
  1946. -- MONOKAI THEME --
  1947. local Colors = {
  1948. Selection = Color3.fromRGB(68, 71, 90),
  1949. Comment = Color3.fromRGB(121, 121, 121),
  1950. InbuiltFunction = Color3.fromRGB(102, 217, 239),
  1951. Function = Color3.fromRGB(226, 226, 226),
  1952. Orange = Color3.fromRGB(255, 184, 108),
  1953. Keyword = Color3.fromRGB(249, 38, 114),
  1954. Operator = Color3.fromRGB(248, 248, 242),
  1955. Red = Color3.fromRGB(255, 85, 85),
  1956. String = Color3.fromRGB(230, 219, 90),
  1957. Text = Color3.fromRGB(248, 248, 242),
  1958. Number = Color3.fromRGB(174, 129, 255)
  1959. };
  1960.  
  1961. local function CenterUI()
  1962. local Absolute = Gui.AbsoluteSize;
  1963. local Size = CodeReview.AbsoluteSize;
  1964. local X, Y = Absolute.X / 2 - (Size.X / 2), Absolute.Y / 2 - (Size.Y / 2);
  1965. CodeReview.Position = UDim2.new(0, X, 0, Y);
  1966. end
  1967.  
  1968. local function GetColor(token)
  1969. if token == "keyword" then
  1970. return Colors.Keyword;
  1971. elseif token == "builtin" then
  1972. return Colors.InbuiltFunction;
  1973. elseif token == "string" then
  1974. return Colors.String;
  1975. elseif token == "comment" then
  1976. return Colors.Comment;
  1977. elseif token == "iden" then
  1978. return Colors.Function;
  1979. elseif token == "number" then
  1980. return Colors.Number;
  1981. elseif token:match("%p") then
  1982. return Colors.Operator;
  1983. else
  1984. return Colors.Text;
  1985. end
  1986. end
  1987.  
  1988. local function ShowCode(String)
  1989. local CurrentLine = 0;
  1990. local _, NumberLines = String:gsub("\n","");
  1991. NumberLines = NumberLines + 1;
  1992.  
  1993. local LineSize, FontSize, Font = 20, 22, "SourceSans";
  1994. local CurrentX, CurrentY = 0, 0;
  1995.  
  1996. local Data = {};
  1997. for token, src in Lexer(String) do
  1998. if src:find("\n") then
  1999. local _, NumberLines = src:gsub("\n","");
  2000. local x, num = src, 0;
  2001. while true do
  2002. local d = x:find("\n");
  2003. if not d then break end;
  2004. local str = x:sub(1, d - 1);
  2005. if num ~= 0 then table.insert(Data, {token, "\n"}) end;
  2006. table.insert(Data, {token, str});
  2007. x = x:sub(d + 1);
  2008. num = num + 1;
  2009. end
  2010. table.insert(Data, {token, "\n"});
  2011. table.insert(Data, {token, x});
  2012. else
  2013. table.insert(Data, {token, src});
  2014. end
  2015. end
  2016.  
  2017. local function UpdateVertical()
  2018. local SizeY, CurrentSize = (NumberLines - 1) * LineSize, Code.AbsoluteSize.Y;
  2019. if CurrentSize < SizeY then
  2020. Code.CanvasSize = UDim2.new(0, 0, 0, SizeY + LineSize * 2);
  2021. VerticalOutline.Visible = true;
  2022. else
  2023. Code.CanvasSize = UDim2.new(0, 0, 0, 0);
  2024. VerticalOutline.Visible = false;
  2025. end
  2026. end
  2027.  
  2028. local SpaceSize;
  2029.  
  2030. for i, data in pairs(Data) do
  2031. --if i % 20 == 0 then RunService.RenderStepped:Wait() UpdateVertical() end
  2032.  
  2033. local token, src = unpack(data);
  2034. local Color = GetColor(token);
  2035. local ThisLineSize = LineSize;
  2036. local good = true;
  2037.  
  2038. if src:sub(1,1) == "\n" then
  2039. CurrentX = 0;
  2040. CurrentY = CurrentY + LineSize;
  2041. src = src:sub(src:find("\n") + 1);
  2042. if #src == 1 then
  2043. good = false;
  2044. end
  2045. end
  2046. if src == " " and SpaceSize then
  2047. good = false;
  2048. CurrentX = CurrentX + SpaceSize;
  2049. end
  2050. if good then
  2051. local Label = Instance.new("TextLabel");
  2052. local _, extra = src:gsub("\t", "");
  2053. --extra = extra * 15;
  2054. extra = extra * (6 * 4)
  2055.  
  2056. local Size = Vector2.new();
  2057. Label.TextColor3 = Color;
  2058. Label.TextXAlignment = "Left";
  2059. Label.Text = src;
  2060. Label.TextSize = FontSize;
  2061. Label.BackgroundTransparency = 1;
  2062. Label.Parent = EditorFrame;
  2063. Label.Font = Font;
  2064. Size = Vector2.new(Label.TextBounds.X + extra, 20);
  2065. Label.Size = UDim2.new(0, Size.X, 0, ThisLineSize);
  2066. Label.Position = UDim2.new(0, CurrentX + extra, 0, CurrentY);
  2067. Label.Name = ("Line%d"):format((CurrentY / LineSize) + 1);
  2068.  
  2069. if src == " " then
  2070. SpaceSize = Label.TextBounds.X;
  2071. end
  2072.  
  2073. if Size.X == 0 then
  2074. Label:Destroy();
  2075. end
  2076.  
  2077. CurrentX = CurrentX + Size.X;
  2078. end
  2079. end
  2080.  
  2081. for i = 1, NumberLines do
  2082. local Label = Instance.new("TextLabel");
  2083. Label.Size = UDim2.new(0.6, 0, 0, 20);
  2084. Label.Position = UDim2.new(0.6, 0, 0, (i - 1) * LineSize);
  2085. Label.BackgroundTransparency = 1;
  2086. Label.AnchorPoint = Vector2.new(0.5, 0);
  2087. Label.Font = "SourceSansSemibold";
  2088. Label.TextScaled = true;
  2089. Label.TextColor3 = Color3.fromRGB(166, 166, 166);
  2090. Label.Text = tostring(i);
  2091. Label.Parent = LineNumbers;
  2092. end
  2093.  
  2094. UpdateVertical();
  2095.  
  2096. local Size = math.clamp((#tostring(NumberLines)) * 12, 35, math.huge);
  2097. LineNumbers.Size = UDim2.new(0, Size, 1, 0);
  2098. EditorFrame.Position = UDim2.new(0, Size + 5, 0, 0);
  2099.  
  2100. if false then -- todo : horizontal scaling
  2101.  
  2102. else
  2103. HorizontalOutline.Visible = false;
  2104. end
  2105. end
  2106.  
  2107. local function ClearEditor()
  2108. EditorFrame:ClearAllChildren();
  2109. for _, obj in pairs(LineNumbers:GetChildren()) do
  2110. if obj.Name ~= "VerticalOutline" then
  2111. obj:Destroy()
  2112. end
  2113. end
  2114. end
  2115.  
  2116. do
  2117. local Scripts = {};
  2118. ScriptEditor = {
  2119. Code = nil,
  2120. IsScript = false,
  2121. CreateScript = function(s, name, code)
  2122. local self = {};
  2123. for k, v in pairs(s) do self[k] = v end;
  2124. self.Code = code;
  2125. self.IsScript = true;
  2126. self.original = s;
  2127. self.Name = name;
  2128.  
  2129. local Clone = Template:Clone();
  2130. local Label = Clone:WaitForChild("Label");
  2131. local Exit = Clone:WaitForChild("Close");
  2132. self.Button = Clone;
  2133.  
  2134. Label.Text = name;
  2135. Clone.Parent = TabFrame;
  2136. Clone.Size = UDim2.new(0, Label.TextBounds.X + 30, 1, 0);
  2137.  
  2138. Clone.MouseButton1Click:Connect(function()
  2139. self:Select();
  2140. end)
  2141. Exit.MouseButton1Click:Connect(function()
  2142. self:Close();
  2143. end);
  2144. ExitButton(Exit);
  2145.  
  2146. self:Select();
  2147.  
  2148. table.insert(Scripts, self);
  2149.  
  2150. return self;
  2151. end,
  2152. Select = function(self)
  2153. self.original:UnselectAll();
  2154. ClearEditor();
  2155. ShowCode(self.Code);
  2156. self.Button.BackgroundColor3 = TabSelectionColor;
  2157. CurrentScript = self;
  2158. Title.Text = ("Script Viewer - %s"):format(self.Name);
  2159. end,
  2160. Unselect = function(self)
  2161. self.Button.BackgroundColor3 = TabColor;
  2162. end,
  2163. Close = function(self)
  2164. if CurrentScript == self then
  2165. CurrentScript = nil;
  2166. Title.Text = "Script Viewer";
  2167. end;
  2168. self.Button:Destroy();
  2169. for i, s in pairs(Scripts) do
  2170. if s == self then
  2171. if Scripts[i - 1] then
  2172. Scripts[i - 1]:Select();
  2173. elseif Scripts[i + 1] then
  2174. Scripts[i + 1]:Select();
  2175. else
  2176. ClearEditor();
  2177. end
  2178. table.remove(Scripts, i);
  2179. break;
  2180. end
  2181. end
  2182. end,
  2183. UnselectAll = function(self)
  2184. if self.IsScript == false then
  2185. for _, sc in pairs(Scripts) do
  2186. sc:Unselect();
  2187. end
  2188. end
  2189. end,
  2190. Show = function(self)
  2191. CodeReview.Visible = true;
  2192. CenterUI();
  2193. end,
  2194. Hide = function(self)
  2195. CodeReview.Visible = false;
  2196. end
  2197. }
  2198. end
  2199.  
  2200. -- Topbar / Ribbon Stuff
  2201. Exit.MouseButton1Click:Connect(function()
  2202. ScriptEditor:Hide();
  2203. end);
  2204. ExitButton(Exit);
  2205.  
  2206. Folder.MouseButton1Click:Connect(function()
  2207. if CurrentScript then
  2208. writefile(("%s.lua"):format(CurrentScript.Name), CurrentScript.Code);
  2209. end
  2210. end);
  2211. Clipboard.MouseButton1Click:Connect(function()
  2212. if CurrentScript then
  2213. setclipboard(CurrentScript.Code);
  2214. end
  2215. end);
  2216.  
  2217. -- so the camera script doesn't zoom in and out during scrolling
  2218. -- still breaks sometimes NICE
  2219. local LastMaxZoom, LastMinZoom;
  2220. CodeReview.MouseEnter:Connect(function()
  2221. LastMaxZoom = Client.CameraMaxZoomDistance;
  2222. LastMinZoom = Client.CameraMinZoomDistance;
  2223. local Head = (Client.Character or Client.CharacterAdded:Wait()):WaitForChild("Head");
  2224. local Zoom = (workspace.CurrentCamera.CoordinateFrame.p - Head.Position).Magnitude;
  2225. Client.CameraMaxZoomDistance = Zoom;
  2226. Client.CameraMinZoomDistance = Zoom;
  2227. end);
  2228. CodeReview.MouseLeave:Connect(function()
  2229. Client.CameraMaxZoomDistance = LastMaxZoom;
  2230. Client.CameraMinZoomDistance = LastMinZoom;
  2231. end);
  2232.  
  2233. CenterUI();
  2234.  
  2235. -- Shift + F for word finder
  2236. local NumKeysDown = 0;
  2237. local function NewFunc(name, state)
  2238. if state == Enum.UserInputState.Begin then
  2239. NumKeysDown = NumKeysDown + 1;
  2240. else
  2241. NumKeysDown = math.clamp(NumKeysDown - 1, 0, 1);
  2242. end
  2243. if NumKeysDown == 2 then
  2244. Finder.Visible = true;
  2245. FinderInput:CaptureFocus();
  2246. end
  2247. return Enum.ContextActionResult.Pass
  2248. end
  2249. ContextAction:BindAction("FindHotkey", NewFunc, false, Enum.KeyCode.F, Enum.KeyCode.LeftShift);
  2250.  
  2251. -- highlight the words on new match(es)
  2252.  
  2253. local match_location, max_matches = 0, 0;
  2254. local matching_str = "";
  2255. local last_wins = {};
  2256.  
  2257. local function update_match()
  2258. Matches.Text = ("%d of %d"):format(match_location, max_matches);
  2259. for _, label in pairs(last_wins) do
  2260. label.BackgroundTransparency = 1;
  2261. end
  2262. local code = CurrentScript;
  2263. if code then
  2264. code = code.Code;
  2265. local matches, bad_code = {}, code;
  2266. while true do
  2267. local match = bad_code:find(matching_str);
  2268. if not match then break end;
  2269. table.insert(matches, match);
  2270. bad_code = bad_code:sub(match + 1);
  2271. end
  2272.  
  2273. local selected = matches[match_location];
  2274. if selected then
  2275. local codetil = code:sub(1, selected);
  2276. local _, lines = codetil:gsub("\n", "");
  2277. lines = lines + 1;
  2278. local match_left = matching_str;
  2279.  
  2280. local line_labels = {};
  2281. for _, label in pairs(EditorFrame:GetChildren()) do
  2282. if label.Name == ("Line%d"):format(lines) and label.Text:match(matching_str) then
  2283. table.insert(line_labels, label);
  2284. end
  2285. end
  2286.  
  2287. local wins = line_labels[match_location] or line_labels[1];
  2288.  
  2289. --[[
  2290. for i, label in pairs(line_labels) do
  2291. -- ffs i give up, for special characters it breaks and for having it
  2292. --work over multiple text labels
  2293. if label.Text:match(match_left) then
  2294. local add = 0;
  2295. local good = true;
  2296. repeat
  2297. local next_label = line_labels[i + add];
  2298. if next_label and next_label.Text:match(match_left) then
  2299. add = add + 1;
  2300. local num = label.Text:match(match_left);
  2301. match_left = match_left:sub(#num + 1);
  2302. if #match_left == 0 then break end;
  2303. else
  2304. good = false;
  2305. break
  2306. end
  2307. until not good or line_labels[i + add] == nil or #match_left == 0;
  2308. if not good then
  2309. match_left = matching_str;
  2310. else
  2311. table.insert(wins, label);
  2312. break
  2313. end
  2314. table.insert(wins, label);
  2315. break;
  2316. end
  2317. end
  2318. ]]
  2319.  
  2320. for i, label in pairs({wins}) do
  2321. if i == 1 then
  2322. Code.CanvasPosition = Vector2.new(0, label.Position.Y.Offset);
  2323. end
  2324. label.BackgroundColor3 = Colors.Selection;
  2325. label.BackgroundTransparency = 0;
  2326. end
  2327. last_wins = {wins};
  2328. end
  2329. end
  2330. end
  2331.  
  2332. local function find(str)
  2333. if #str == 0 then return end;
  2334. match_location = 1;
  2335. matching_str = str:gsub("[%(%)%.]+", "%%%1");
  2336. local code = CurrentScript;
  2337. if code then
  2338. code = code.Code;
  2339. local _, matches = code:gsub(str, "");
  2340. max_matches = matches;
  2341. update_match();
  2342. end
  2343. end
  2344.  
  2345. ExitButton(FinderExit);
  2346. FinderExit.MouseButton1Click:Connect(function()
  2347. Finder.Visible = false;
  2348. for _, label in pairs(last_wins) do
  2349. label.BackgroundTransparency = 1;
  2350. end
  2351. end)
  2352. DownArrow.MouseButton1Click:Connect(function()
  2353. match_location = match_location + 1;
  2354. if match_location > max_matches then
  2355. match_location = 1;
  2356. end
  2357. update_match();
  2358. end);
  2359. UpArrow.MouseButton1Click:Connect(function()
  2360. match_location = match_location - 1;
  2361. if match_location <= 0 then
  2362. match_location = max_matches;
  2363. end
  2364. update_match();
  2365. end);
  2366.  
  2367. FinderInput.FocusLost:Connect(function()
  2368. find(FinderInput.Text);
  2369. end);
  2370.  
  2371. update_match();
  2372.  
  2373. end
  2374. end
  2375.  
  2376. -- loading --
  2377.  
  2378. local function Load()
  2379. local OriginalSize = ExplorerFrame.Size;
  2380. local OriginalSize2 = PropertiesFrame.Size;
  2381.  
  2382. ExplorerFrame.ClipsDescendants = true;
  2383. PropertiesFrame.ClipsDescendants = true;
  2384.  
  2385. ExplorerFrame.Size = UDim2.new(OriginalSize.X.Scale, OriginalSize.X.Offset, 0, 0);
  2386. PropertiesFrame.Size = UDim2.new(OriginalSize2.X.Scale, OriginalSize2.X.Offset, 0, 0);
  2387.  
  2388. ExplorerFrame.Visible = true;
  2389. PropertiesFrame.Visible = true;
  2390.  
  2391. ExplorerFrame:TweenSize(OriginalSize, 1, Enum.EasingStyle.Linear, 0.2, 1);
  2392. wait(0.2);
  2393. PropertiesFrame:TweenSize(OriginalSize2, 1, Enum.EasingStyle.Linear, 0.2, 1);
  2394. wait(0.2);
  2395.  
  2396. ExplorerFrame.ClipsDescendants = false;
  2397. PropertiesFrame.ClipsDescendants = false;
  2398.  
  2399. end
  2400.  
  2401. -----------
  2402.  
  2403. local function Boot()
  2404. local CodeReview = Gui:WaitForChild("CodeReview");
  2405.  
  2406. drag(ExplorerFrame:WaitForChild("Topbar"), ExplorerFrame);
  2407. drag(CodeReview:WaitForChild("Ribbon"), CodeReview);
  2408.  
  2409. FillList();
  2410. UpdateList(GetShowList());
  2411. UpdateScrollbar();
  2412. local function HoverUpdates()
  2413. GetFurthestOut();
  2414. for _, object in pairs(ListObjects) do
  2415. object:UpdateHoverEnd();
  2416. end
  2417. end
  2418. table.insert(ChildAddedUpdates, HoverUpdates);
  2419. table.insert(ScrollUpdates, HoverUpdates);
  2420. table.insert(ScrollUpdates, UpdateSelections);
  2421.  
  2422. delay(0, Load);
  2423.  
  2424. -- for studio testing --
  2425. if RunService:IsStudio() then
  2426. delay(1, function()
  2427. --[[
  2428. ScriptEditor:Show();
  2429. ScriptEditor:CreateScript("test", 'print("Hello World!")\n--comment\nfor i = 1, 25 / 5 do\n\tlocal bye = 1;\nend');
  2430.  
  2431. Notify:new("an error", "an error");]]
  2432. end);
  2433. else
  2434. Gui.Name = RandomString(10);
  2435. for _, object in pairs(Gui:GetDescendants()) do
  2436. object.Name = RandomString(10);
  2437. end
  2438.  
  2439. Gui.Parent = game:GetService("CoreGui");
  2440. end
  2441.  
  2442. -- temporary?
  2443.  
  2444. RunService.RenderStepped:Connect(function()
  2445. PropertiesFrame.Position = ExplorerFrame.Position + UDim2.new(0, 0, 0, ExplorerFrame.AbsoluteSize.Y);
  2446. end);
  2447. ExplorerFrame:GetPropertyChangedSignal("ZIndex"):Connect(function()
  2448. SetZIndex(PropertiesFrame, ExplorerFrame.ZIndex - 1);
  2449. end);
  2450.  
  2451. --print("Successfully booted in " .. tostring(tick() - START) .. " seconds!");
  2452. end
  2453.  
  2454. Boot();
Add Comment
Please, Sign In to add comment