Advertisement
Vzurxy

FrostHook

Dec 12th, 2019
631
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 92.15 KB | None | 0 0
  1. --[[
  2.  _______  _______  _______  _______ _________          _______  _______  _          _______  _______          
  3. (  ____ \(  ____ )(  ___  )(  ____ \\__   __/|\     /|(  ___  )(  ___  )| \    /\  (  ____ \(  ____ )|\     /|
  4. | (    \/| (    )|| (   ) || (    \/   ) (   | )   ( || (   ) || (   ) ||  \  / /  | (    \/| (    )|( \   / )
  5. | (__    | (____)|| |   | || (_____    | |   | (___) || |   | || |   | ||  (_/ /   | (_____ | (____)| \ (_) /
  6. |  __)   |     __)| |   | |(_____  )   | |   |  ___  || |   | || |   | ||   _ (    (_____  )|  _____)  \   /  
  7. | (      | (\ (   | |   | |      ) |   | |   | (   ) || |   | || |   | ||  ( \ \         ) || (         ) (  
  8. | )      | ) \ \__| (___) |/\____) |   | |   | )   ( || (___) || (___) ||  /  \ \  /\____) || )         | |  
  9. |/       |/   \__/(_______)\_______)   )_(   |/     \|(_______)(_______)|_/    \/  \_______)|/          \_/  
  10.  
  11. ~ Nootchtai; 12/12/2019;
  12.  
  13. Possbile future features:
  14.     Upvalue scanning
  15.     Viewing all hooks in real time in an output style window
  16. Not yet implemented:
  17.     /shrug
  18. --[==[Mandatory Functions for operation]==]--
  19.         * hookfunction
  20.         * replaceclosure
  21.         * newcclosure
  22.         * getreg
  23.         * setclipboard
  24.         * setreadonly
  25.         * checkcaller
  26.         * debug library (period)
  27. ]]--
  28.  
  29. local FrostHook = {
  30.     Tooltips = true, -- Tooltips for understanding what certain buttons do.
  31.     Monitoring = { -- What remotes/bindables to monitor.
  32.         ["RemoteEvent"]=true, -- :FireServer(arguments)
  33.         ["RemoteFunction"]=true, -- :InvokeServer(arguments)
  34.         ["BindableEvent"]=true, -- :Fire(arguments)
  35.         ["BindableFunction"]=true, -- :Invoke(arguments)
  36.         ["__namecall"]=true, -- FireServer(remote, arguments)
  37.         -- maybe hook __index?? /shrug
  38.         ["HttpGet"]=true, -- game:HttpGet(...)
  39.         ["HttpPost"]=true, -- game:HttpPost(...)
  40.         ["GetObjects"]=true, -- game:GetObjects(...)
  41.     },
  42.     Ignored_Remotes = { -- Ignore remotes by name
  43.         -- ROBLOCK CHAT STUFFS
  44.         ["GetInitDataRequest"]=true,
  45.         ["MutePlayerRequest"]=true,
  46.         ["UnMutePlayerRequest"]=true,
  47.         ["ChannelNameColorUpdated"]=true,
  48.         ["OnChannelJoined"]=true,
  49.         ["OnChannelLeft"]=true,
  50.         ["OnMainChannelSet"]=true,
  51.         ["OnMessageDoneFiltering"]=true,
  52.         ["OnMuted"]=true,
  53.         ["OnNewMessage"]=true,
  54.         ["OnNewSystemMessage"]=true,
  55.         ["MessagesChanged"]=true,
  56.         ["MessagePosted"]=true,
  57.         ["ChatBarFocusChanged"]=true,
  58.         ["OnUnmuted"]=true,
  59.         ["SayMessageRequest"]=true,
  60.         ["SetBlockedUserIdsRequest"]=true,
  61.         -- /shrug
  62.         ["Event"]=true, -- nani wonder where this is comin from
  63.     },
  64.     Data_Type_Colors = { -- The colors of the data types in the call viewer (unknown will be white)
  65.         ["string"] = Color3.fromRGB(85, 170, 127),
  66.         ["table"] = Color3.fromRGB(60, 60, 60),
  67.         ["boolean"] = Color3.fromRGB(85, 170, 255),
  68.     },
  69.     EditorColors = { -- The color types for the Code editor
  70.         ["Word"] = Color3.fromRGB(58, 117, 175),
  71.         ["Nil"] = Color3.fromRGB(115, 115, 172),
  72.         ["Table"] = Color3.fromRGB(181, 120, 90),
  73.         ["Scope"] = Color3.fromRGB(194, 64, 97),
  74.         ["Comment"] = Color3.fromRGB(50, 50, 50),
  75.         ["String"] = Color3.fromRGB(85, 170, 127),
  76.     },
  77.     RemoteColors = { -- The colors for the remotes in the Cache + List views.
  78.         ["RemoteEvent"] = Color3.fromRGB(85, 170, 255),
  79.         ["RemoteFunction"] = Color3.fromRGB(85, 170, 255),
  80.         ["BindableEvent"] = Color3.fromRGB(85, 170, 255),
  81.         ["BindableFunction"] = Color3.fromRGB(85, 170, 255),
  82.     },
  83.     HttpColors = {
  84.         ["HttpGet"] = Color3.fromRGB(85, 170, 255),
  85.         ["HttpPost"] = Color3.fromRGB(85, 170, 255),
  86.         ["GetObjects"] = Color3.fromRGB(85, 170, 255),
  87.     },
  88.     Constraints = { -- Interface Constraints for resizing.
  89.         Min = UDim2.new(0,400,0,250),
  90.         Max = UDim2.new(0,800,0,500)
  91.     },
  92.     env = { -- Inherited from Hydroxide.
  93.         get_upvalues = debug.getupvalues or getupvalues or getupvals or false,
  94.         get_upvalue = debug.getupvalue or getupvalue or getupval or false,
  95.         get_metatable = getrawmetatable or debug.getmetatable or false,
  96.         get_namecall = getnamecallmethod or false,
  97.         get_reg = getreg or debug.getregistry or false,
  98.         set_namecall = setnamecallmethod or false,
  99.         set_readonly = setreadonly or make_writeable or false,
  100.         is_l_closure = islclosure or (iscclosure and function(closure) return not iscclosure(closure) end) or false,
  101.         is_x_closure = is_synapse_function or is_protosmasher_closure or issentinelclosure or false,
  102.         hook_function = hookfunction or hookfunc or false,
  103.         new_cclosure = newcclosure or false,
  104.         to_clipboard = (syn and syn.write_clipboard) or writeclipboard or toclipboard or setclipboard or false,
  105.         check_caller = checkcaller or false,
  106.         replace_closure = replaceclosure or false,
  107.     },
  108.     Services = setmetatable({},{__index = function(self, index)
  109.         return game:GetService(index) or nil;
  110.     end}),
  111.  
  112.     -- Internals --
  113.     Search_Directories = {
  114.         game:GetService("ReplicatedStorage"),
  115.         game:GetService("Players").LocalPlayer,
  116.         game:GetService("Players").LocalPlayer.Character,
  117.     },
  118.     Cache = {
  119.         _entry = nil,
  120.     },
  121.     HttpCache = {
  122.         _entry = nil,
  123.     },
  124.     Hook_Cache = {},
  125.     FireCounts = {
  126.         ["RemoteEvent"] = 0,
  127.         ["RemoteFunction"] = 0,
  128.         ["BindableEvent"] = 0,
  129.         ["BindableFunction"] = 0,
  130.         ["HttpGet"] = 0,
  131.         ["HttpPost"] = 0,
  132.         ["GetObjects"] = 0,
  133.         _updated = false,
  134.         _latest = false,
  135.     },
  136.     RemoteFuncRef = {
  137.         ["RemoteFunction"] = "InvokeServer",
  138.         ["RemoteEvent"] = "FireServer",
  139.         ["BindableFunction"] = "Invoke",
  140.         ["BindableEvent"] = "Fire",
  141.     },
  142.     HttpFuncRef = {
  143.         ["GetObjects"] = game.GetObjects,
  144.         ["HttpGet"] = game.HttpGet,
  145.         ["HttpPost"] = game.HttpPost,
  146.     },
  147.     Internal_Ignored = {},
  148.     Interface = game:GetObjects("rbxassetid://4507087024")[1],
  149.     Connections = {},
  150.     CustomDrag = {
  151.         DragActive = {},
  152.         ResizeActive = {},
  153.     },
  154.     ScriptGeneration = {
  155.         AppendBeginning = "\n", -- These two will be for appending comments to the beggining/end of the generated script.
  156.         AppendEnding = "\n",
  157.     },
  158.     TextEditor = {
  159.         Interface = script.Parent,
  160.         TabSize = 8,
  161.         Font = "SourceSansSemibold",
  162.         FontSize = 14,
  163.         Cache = {},
  164.         LineCache = {_len=0},
  165.         Imported = false,
  166.     },
  167. }
  168.  
  169. FrostHook.Keywords = { -- Keyword string matching for code editor.
  170.     ["and"] = {FrostHook.EditorColors.Word, "[%s-]", "[%s-]"},
  171.     ["break"] = {FrostHook.EditorColors.Word, "[%s?%p?]","[%s?%p?]"},
  172.     ["do"] = {FrostHook.EditorColors.Word, "%s*", "[%s]"},
  173.     ["if"] = {FrostHook.EditorColors.Word, "%s*", "[%s]"},
  174.     ["else"] = {FrostHook.EditorColors.Word, "[%s]", "[%s]"},
  175.     ["elseif"] = {FrostHook.EditorColors.Word, "[%s]", "[%s]"},
  176.     ["then"] = {FrostHook.EditorColors.Word, "[%s]", "[%s]"},
  177.     ["end"] = {FrostHook.EditorColors.Word, "%s*%p*", "[%s-%p-]"},
  178.     ["true"] = {FrostHook.EditorColors.Nil, "%s*", "[%s-%p-]"},
  179.     ["false"] = {FrostHook.EditorColors.Nil, "%s*", "[%s-%p-]"},
  180.     ["for"] = {FrostHook.EditorColors.Word, "%s*", "%s"},
  181.     ["function"] = {FrostHook.EditorColors.Word, "%s?%p?", "[%s?%p?]"},
  182.     ["in"] = {FrostHook.EditorColors.Word, ".", "[%s]"},
  183.     ["local"] = {FrostHook.EditorColors.Scope, "%s?", "[%s]"},
  184.     ["nil"] = {FrostHook.EditorColors.Nil, "%s?", "[%s?%p?]"},
  185.     ["not"] = {FrostHook.EditorColors.Word, "[%s?%p?]", "[%s?%p?]"},
  186.     ["or"] = {FrostHook.EditorColors.Word, "[%s]", "[%s]"},
  187.     ["repeat"] = {FrostHook.EditorColors.Word, "%s*%p*", "[%s]"},
  188.     ["return"] = {FrostHook.EditorColors.Word, "[%s]", "[%s?%p?]"},
  189.     ["until"] = {FrostHook.EditorColors.Word, "[%s]", "[%s]"},
  190.     ["while"] = {FrostHook.EditorColors.Word, "[%s]*", "[%s]*"},
  191.  
  192.     ["self"] = {FrostHook.EditorColors.Nil, "", ""},
  193.     ["game"] = {FrostHook.EditorColors.Word, "", ""},
  194.     ["script"] = {FrostHook.EditorColors.Word, "", ""},
  195.  
  196.     ["table"] = {FrostHook.EditorColors.Table, "[.]*", "%."},
  197.     ["math"] = {FrostHook.EditorColors.Table, "[.]*", "%."},
  198.     ["string"] = {FrostHook.EditorColors.Table, "[.]*", "%."},
  199.  
  200.     ["print"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  201.     ["loadstring"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  202.     ["tostring"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  203.     ["dofile"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  204.     ["require"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  205.     ["tonumber"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  206.     ["writefile"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  207.     ["readfile"] = {FrostHook.EditorColors.Word, "[.]*", "[%p]"},
  208. }
  209.  
  210. for i,v in next, FrostHook.env do
  211.     assert(v, "Your exploit does not support FrostHook's Spy Tool :(")
  212. end
  213.  
  214. repeat
  215.     wait()
  216. until game:IsLoaded();
  217.  
  218. local Mouse = FrostHook.Services.Players.LocalPlayer:GetMouse();
  219.  
  220. do -- FrostHook Main Object
  221.     local metadata = {};
  222.     local methods = {
  223.         Destroy = function(self)
  224.             getgenv().FrostHookSpy = nil;
  225.             self.Interface:Destroy();
  226.             for _,Connection in pairs(self.Connections) do
  227.                 Connection:Disconnect();
  228.             end
  229.             self:StopTracking();
  230.             FrostHook = nil;
  231.         end,
  232.         RegisterConnection = function(self, event, runtime_func)
  233.             local connection;
  234.             connection = event:Connect(function(...)
  235.                 local arguments = {...}
  236.                 local status,error_msg = pcall(function()
  237.                     return runtime_func(unpack(arguments))
  238.                 end);
  239.                 if not status then
  240.                     warn("Connection fault: "..tostring(error_msg))
  241.                     for i,v in pairs(FrostHook.Connections) do
  242.                         if v == connection then
  243.                             table.remove(FrostHook.Connections, i)
  244.                             v:Disconnect();
  245.                         end
  246.                     end
  247.                 end
  248.             end)
  249.             table.insert(self.Connections, connection);
  250.             return connection;
  251.         end,
  252.         RequestCache = function(self, reqtype, varargs)
  253.             if self.HttpCache[reqtype] then
  254.                 table.insert(self.HttpCache[reqtype].Logs, varargs)
  255.                 self.FireCounts[reqtype] = self.FireCounts[reqtype] - self.HttpCache[reqtype].FireCount;
  256.                 self.HttpCache[reqtype].FireCount = #self.HttpCache[reqtype].Logs;
  257.                 self.FireCounts[reqtype] = self.FireCounts[reqtype] + self.HttpCache[reqtype].FireCount;
  258.                 self.FireCounts["_latest"]:Fire(reqtype); -- hmmm idk about this
  259.                 self.HttpCache[reqtype].Updated:Fire("Add", varargs);
  260.                 self.FireCounts._updated:Fire(true);
  261.             elseif not self.HttpCache[reqtype] then
  262.                 local updated = Instance.new("BindableEvent")
  263.                 updated.Name = "Updated";
  264.                 self.Internal_Ignored[updated] = true;
  265.  
  266.                 self.HttpCache[reqtype] = {
  267.                     Logs = {
  268.                         varargs,
  269.                     },
  270.                     Spying = true,
  271.                     FireCount = 1,
  272.                     Updated = updated;
  273.                 }
  274.  
  275.                 self.FireCounts[reqtype] = self.FireCounts[reqtype] + 1;
  276.                 self.FireCounts._updated:Fire(true);
  277.             end
  278.         end,
  279.         ClearRequestCache = function(self, reqtype)
  280.             if self.HttpCache[reqtype] then
  281.                 self.HttpCache[reqtype].Logs = {};
  282.                 self.FireCounts[reqtype] = self.FireCounts[reqtype] - self.HttpCache[reqtype].FireCount;
  283.                 self.HttpCache[reqtype].FireCount = 0;
  284.                 self.HttpCache[reqtype].Updated:Fire("Clear");
  285.                 self.FireCounts._updated:Fire();
  286.             end
  287.         end,
  288.         CacheData = function(self, remote, varargs, populate)
  289.             if populate and not self.Cache[remote] then -- populate the cache with already known remotes/bindables
  290.                 local updated = Instance.new("BindableEvent")
  291.                 updated.Name = "Updated";
  292.                 self.Internal_Ignored[updated] = true;
  293.  
  294.                 self.Cache[remote] = {
  295.                     Logs = {},
  296.                     Spying = true,
  297.                     FireCount = 0,
  298.                     Updated = updated,
  299.                 }
  300.                 return;
  301.             end
  302.  
  303.             if self.Cache[remote] then
  304.                 local s,e = pcall(function()
  305.                     table.insert(self.Cache[remote].Logs, varargs)
  306.                     self.FireCounts[remote.ClassName] = self.FireCounts[remote.ClassName] - self.Cache[remote].FireCount; -- take away old firecount
  307.                     self.Cache[remote].FireCount = #self.Cache[remote].Logs;
  308.                     self.FireCounts[remote.ClassName] = self.FireCounts[remote.ClassName] + self.Cache[remote].FireCount; -- add new firecount
  309.                     self.FireCounts["_latest"]:Fire(remote); -- The latest updated remote
  310.  
  311.                     self.Cache[remote].Updated:Fire("Add", varargs);
  312.                     self.FireCounts._updated:Fire(true);
  313.                 end)
  314.                 if not s then
  315.                     warn("FH Cache error: ", e);
  316.                 end
  317.             else -- First time set-up for the unexpected data.
  318.                 self.FireCounts[remote.ClassName] = self.FireCounts[remote.ClassName] + 1;
  319.  
  320.                 local updated = Instance.new("BindableEvent")
  321.                 updated.Name = "Updated";
  322.                 self.Internal_Ignored[updated] = true;
  323.  
  324.                 self.Cache[remote] = {
  325.                     Logs = {
  326.                         varargs,
  327.                     },
  328.                     Spying = true,
  329.                     FireCount = 1,
  330.                     Updated = updated,
  331.                 }
  332.             end
  333.         end,
  334.         ClearCacheData = function(self, remote)
  335.             if self.Cache[remote] then
  336.                 self.Cache[remote].Logs = {}; -- clear cache
  337.                 self.FireCounts[remote.ClassName] = self.FireCounts[remote.ClassName] - self.Cache[remote].FireCount;
  338.                 self.Cache[remote].FireCount = 0;
  339.                 self.Cache[remote].Updated:Fire("Clear");
  340.                 self.FireCounts._updated:Fire();
  341.             end
  342.         end,
  343.         IsRemote = function(self, obj)
  344.             return obj.ClassName == "RemoteEvent" or obj.ClassName == "RemoteFunction" or obj.ClassName == "BindableEvent" or obj.ClassName == "BindableFunction"
  345.         end,
  346.         TrackHttp = function(self)
  347.             for name,func in pairs(self.HttpFuncRef) do
  348.                 if self.Monitoring[name] then
  349.                     local temp_hook;
  350.                     temp_hook = self.env.hook_function(func, self.env.new_cclosure(function(req, ...)
  351.                         local varargs = {...}
  352.                         if self.HttpCache[name] and self.HttpCache[name].Spying then
  353.                             self:RequestCache(name, varargs);
  354.                         elseif not self.HttpCache[name] then
  355.                             self:RequestCache(name, varargs);
  356.                         end
  357.                         return temp_hook(name, ...)
  358.                     end))
  359.                     self.Hook_Cache[name] = temp_hook;
  360.                 end
  361.             end
  362.         end,
  363.         TrackRemotes = function(self)
  364.             local to_hook = {
  365.                 ["RemoteEvent"] = Instance.new("RemoteEvent").FireServer,
  366.                 ["RemoteFunction"] = Instance.new("RemoteFunction").InvokeServer,
  367.                 ["BindableEvent"] = Instance.new("BindableEvent").Fire,
  368.                 ["BindableFunction"] = Instance.new("BindableFunction").Invoke,
  369.             }
  370.        
  371.             for class,func in pairs(to_hook) do
  372.                 if self.Monitoring[class] then
  373.                     local temp_hook;
  374.                     temp_hook = self.env.hook_function(func, self.env.new_cclosure(function(remote, ...)
  375.                         local varargs = {...};
  376.                         if self.env.check_caller() or (self.Internal_Ignored[remote]) then
  377.                             return temp_hook(remote, ...);
  378.                         end
  379.  
  380.                         if not(self.Ignored_Remotes[remote.Name]) then
  381.                             if self.Cache[remote] and self.Cache[remote].Spying then
  382.                                 self:CacheData(remote, varargs)
  383.                             elseif not self.Cache[remote] then
  384.                                 self:CacheData(remote, varargs)
  385.                             end
  386.                         end
  387.                         return temp_hook(remote, ...);
  388.                     end))
  389.                     self.Hook_Cache[class] = temp_hook;
  390.                 end
  391.             end
  392.  
  393.             if self.Monitoring["__namecall"] then
  394.                 local gmeta = getrawmetatable(game);
  395.                 self.Hook_Cache["namecall"] = gmeta.__namecall;
  396.                 self.env.set_readonly(gmeta, false);
  397.  
  398.                 local namecall = Instance.new("BindableFunction")
  399.                 self.Internal_Ignored[namecall] = true;
  400.                 namecall.OnInvoke = self.env.new_cclosure(function(remote, varargs)
  401.                     if not(self.Ignored_Remotes[remote.Name]) then
  402.                         if self.Cache[remote] and self.Cache[remote].Spying then
  403.                             self:CacheData(remote, varargs)
  404.                         elseif not self.Cache[remote] then
  405.                             self:CacheData(remote, varargs)
  406.                         end
  407.                     end
  408.                 end);
  409.  
  410.                 gmeta.__namecall = self.env.new_cclosure(function(remote, ...)
  411.                     local varargs = {...};
  412.  
  413.                     if self:IsRemote(remote) then
  414.                         if self.env.check_caller() or (self.Internal_Ignored[remote]) then
  415.                             return self.Hook_Cache["namecall"](remote, ...);
  416.                         end
  417.                         namecall.Invoke(namecall, remote, varargs);
  418.                     end
  419.                    
  420.                     return self.Hook_Cache["namecall"](remote, ...);
  421.                 end)
  422.  
  423.                 self.env.set_readonly(gmeta, true);
  424.             end
  425.         end,
  426.         StopTracking = function(self) -- This will also stop tracking http calls in future
  427.             local to_fix = {
  428.                 ["RemoteEvent"] = Instance.new("RemoteEvent").FireServer,
  429.                 ["RemoteFunction"] = Instance.new("RemoteFunction").InvokeServer,
  430.                 ["BindableEvent"] = Instance.new("BindableEvent").Fire,
  431.                 ["BindableFunction"] = Instance.new("BindableFunction").Invoke,
  432.             }
  433.  
  434.             for class,func in pairs(to_fix) do
  435.                 for ref,hook in pairs(self.Hook_Cache) do
  436.                     if class == ref then
  437.                         self.env.replace_closure(func, hook);
  438.                     end
  439.                 end
  440.             end
  441.  
  442.             for name,func in pairs(self.HttpFuncRef) do
  443.                 for ref,hook in pairs(self.Hook_Cache) do
  444.                     if name == ref then
  445.                         self.env.replace_closure(func, hook);
  446.                     end
  447.                 end
  448.             end
  449.  
  450.             if self.Monitoring["__namecall"] and self.Hook_Cache["namecall"] then
  451.                 local gmeta = getrawmetatable(game);
  452.                 self.env.set_readonly(gmeta, false)
  453.                 gmeta.__namecall = self.Hook_Cache["namecall"];
  454.                 self.env.set_readonly(gmeta, true);
  455.             end
  456.         end,
  457.         SetTooltip = function(self, this_object, description)
  458.             if not(self.Tooltips) then
  459.                 return;
  460.             end
  461.  
  462.             local tooltip = self.Interface.Templates.Tooltip;
  463.  
  464.             local textSize = game:GetService("TextService"):GetTextSize(description, 14, "SourceSansBold", Vector2.new(math.huge,20))
  465.  
  466.             this_object.MouseEnter:Connect(function()
  467.                 tooltip.Text = description;
  468.                 tooltip.Size = UDim2.new(0,textSize.X + 5,0,20)
  469.                 tooltip.Visible = true;
  470.             end)
  471.  
  472.             this_object.MouseLeave:Connect(function()
  473.                 tooltip.Text = "";
  474.                 tooltip.Visible = false;
  475.             end)
  476.  
  477.             this_object.AncestryChanged:Connect(function()
  478.                 tooltip.Text = "";
  479.                 tooltip.Visible = false;
  480.             end)
  481.         end,
  482.         DatatypeFormat = function(self, data)
  483.             local datatype = typeof(data);
  484.             local cleaned_string = tostring(data);
  485.             local datacol = Color3.new(1,1,1)
  486.             local potential_col = self.Data_Type_Colors[datatype]
  487.            
  488.             if potential_col ~= nil then
  489.                 datacol = potential_col;
  490.             end;
  491.  
  492.             if datatype == "string" then
  493.                 cleaned_string = '"'..tostring(data)..'"';
  494.             elseif datatype == "Vector3" then
  495.                 cleaned_string = "Vector3.new("..table.concat({data.X,data.Y,data.Z}, ", ")..")"
  496.             elseif datatype == "UDim2" then
  497.                 cleaned_string = "UDim2.new("..table.concat({data.X.Scale,data.X.Offset,data.Y.Scale,data.Y.Offset}, ", ")..")"
  498.             elseif datatype == "UDim" then
  499.                 cleaned_string = "UDim.new("..table.concat({data.Scale,data.Offset}, ", ")..")"
  500.             elseif datatype == "CFrame" then
  501.                 cleaned_string = "CFrame.new("..table.concat({data.X,data.Y,data.Z}, ", ")..")" -- this is a piss poor way of handling cframes
  502.             elseif datatype == "Vector2" then
  503.                 cleaned_string = "Vector2.new("..table.concat({data.X,data.Y}, ", ")..")"
  504.             end
  505.             return datacol, cleaned_string;
  506.         end,
  507.     };
  508.  
  509.     metadata.__index = function(self, index)
  510.         if methods[index] then
  511.             return function(s, ...)
  512.                 return methods[index](self, ...);
  513.             end
  514.         end
  515.     end
  516.  
  517.     metadata.__call = function(self)
  518.         assert(getgenv().FrostHookSpy==nil, "FrostHook RemoteSpy is already running!")
  519.         getgenv().FrostHookSpy = true;
  520.  
  521.         if self.Services.CoreGui:FindFirstChild("FH_SPY") then
  522.             self.Services.CoreGui.FH_SPY:Destroy();
  523.         end
  524.  
  525.         if syn and syn.protectgui then
  526.             syn.protectgui(self.Interface);
  527.         end
  528.  
  529.         self.Interface.Parent = self.Services.CoreGui;
  530.  
  531.         do -- set up the entry added bindable
  532.             local Entry = Instance.new("BindableEvent")
  533.             Entry.Name = "Entry";
  534.             self.Cache["_entry"] = Entry;
  535.             self.Internal_Ignored[Entry] = true;
  536.             local Latest = Instance.new("BindableEvent")
  537.             Latest.Name = "Latest"
  538.             self.FireCounts["_latest"] = Latest;
  539.             self.Internal_Ignored[Latest] = true;
  540.             local FCUpdated = Instance.new("BindableEvent")
  541.             FCUpdated.Name = "FireCountUpdated";
  542.             self.FireCounts._updated = FCUpdated;
  543.             self.Internal_Ignored[FCUpdated] = true;
  544.         end
  545.  
  546.         do -- Handle Interface
  547.             local Spy = self.Interface;
  548.                 local topbar = Spy.Topbar;
  549.                     local Main = topbar.Main;
  550.                         local drag = Main.drag
  551.                         local MainPanel = Main.MainPanel;
  552.                         local TabPanel = Main.TabPanel;
  553.                             local SearchBar = TabPanel.Space.Search;
  554.                             local ExecuteButton = TabPanel.Space.Execute;
  555.                         local CloseButton = Main.Topbar_shadow.TopbarButtons.Close;
  556.                         self:SetTooltip(CloseButton, "Close window")
  557.                         local DestroyButton = Main.Topbar_shadow.TopbarButtons:FindFirstChild("Destroy"); -- Yuck, .Destroy thinks it's the roblox method
  558.                         self:SetTooltip(DestroyButton, "Spy:Destroy()")
  559.                 local Templates = Spy.Templates;
  560.                     local tooltip = Templates.Tooltip;
  561.                     local ExampleCall = Templates.ExampleCall;
  562.                 local OpenButton = Spy.Open.button;
  563.             local CurrentTab = "List";
  564.             local ViewingType = "";
  565.             local Panels,Categories,Tabs = {},{},{};
  566.             local HoveringObject;
  567.             local HoveringCallData = {
  568.                 object = nil,
  569.                 varargs = nil,
  570.             };
  571.             local AddRemoveOverride = false;
  572.             local TabSize = 10;
  573.  
  574.             local function CreateObjectTemplate(object, Remote)
  575.                 local ObjectFrame = object:Clone();
  576.                 ObjectFrame.Name = tostring(Remote);
  577.                 ObjectFrame.Label.Text = tostring(Remote);
  578.                
  579.                 local _textSize = game:GetService("TextService"):GetTextSize(tostring(Remote), 14, "SourceSansBold", Vector2.new(math.huge,20))
  580.                
  581.                 ObjectFrame.Label.Size = UDim2.new(0,_textSize.X + 5,1,0)
  582.  
  583.                 local _info = TweenInfo.new(0.2,Enum.EasingStyle.Quad,Enum.EasingDirection.Out,0,false,0)
  584.                 local _select = game:GetService("TweenService"):Create(ObjectFrame.Label, _info, {["TextStrokeTransparency"]=0.1})
  585.                 local _unselect = game:GetService("TweenService"):Create(ObjectFrame.Label, _info, {["TextStrokeTransparency"]=1})
  586.  
  587.                 ObjectFrame.MouseEnter:Connect(function()
  588.                     HoveringObject = Remote;
  589.                     _select:Play();
  590.                 end)
  591.                
  592.                 ObjectFrame.MouseLeave:Connect(function()
  593.                     if HoveringObject == Remote then
  594.                         HoveringObject = nil;
  595.                     end
  596.                     _unselect:Play();
  597.                 end)
  598.                
  599.                 ObjectFrame.Visible = true;
  600.                 return ObjectFrame;
  601.             end
  602.  
  603.             local function PopulateObject2(Remote, Data)
  604.                 local ObjectFrame = CreateObjectTemplate(Templates.Object_2, Remote)
  605.                 local switch = ObjectFrame.Switch_Toggle;
  606.  
  607.                 local thisRemoteColor = self.RemoteColors[Remote.ClassName];
  608.                 ObjectFrame.Emblem.ImageColor3 = thisRemoteColor
  609.                
  610.                 local function toggle_switch(bool)
  611.                     if not bool then
  612.                         switch.Visible_Switch.ImageColor3 = Color3.new(1,1,1);
  613.                         switch.Visible_Switch.Position = UDim2.new(0,7,0.5,0);
  614.                         return
  615.                     end
  616.                     switch.Visible_Switch.ImageColor3 = thisRemoteColor;
  617.                     switch.Visible_Switch.Position = UDim2.new(1,-21,0.5,0);
  618.                 end
  619.  
  620.                 toggle_switch(Data.Spying)
  621.  
  622.                 local cached;
  623.                 cached = Data.Updated.Event:Connect(function(Operation)
  624.                     if Operation == "SpyChange" then
  625.                         toggle_switch(Data.Spying)
  626.                         return;
  627.                     end
  628.                 end)
  629.  
  630.                 ObjectFrame.AncestryChanged:Connect(function()
  631.                     if ObjectFrame.Parent == nil then
  632.                         cached:Disconnect();
  633.                     end
  634.                 end)
  635.  
  636.                 switch.Interact.MouseButton1Down:Connect(function()
  637.                     Data.Spying = not Data.Spying;
  638.                     toggle_switch(Data.Spying)
  639.                 end)
  640.  
  641.                 ObjectFrame.Parent = Panels["List"];
  642.             end
  643.  
  644.             local function PopulateHttpObject2(Type, Data)
  645.                 local ObjectFrame = CreateObjectTemplate(Templates.Object_2, Type)
  646.                 local switch = ObjectFrame.Switch_Toggle;
  647.  
  648.                 local thisReqColor = self.HttpColors[Type];
  649.                 ObjectFrame.Emblem.ImageColor3 = thisReqColor
  650.                
  651.                 local function toggle_switch(bool)
  652.                     if not bool then
  653.                         switch.Visible_Switch.ImageColor3 = Color3.new(1,1,1);
  654.                         switch.Visible_Switch.Position = UDim2.new(0,7,0.5,0);
  655.                         return
  656.                     end
  657.                     switch.Visible_Switch.ImageColor3 = thisReqColor;
  658.                     switch.Visible_Switch.Position = UDim2.new(1,-21,0.5,0);
  659.                 end
  660.  
  661.                 toggle_switch(Data.Spying)
  662.  
  663.                 local cached;
  664.                 cached = Data.Updated.Event:Connect(function(Operation)
  665.                     if Operation == "SpyChange" then
  666.                         toggle_switch(Data.Spying)
  667.                         return;
  668.                     end
  669.                 end)
  670.  
  671.                 ObjectFrame.AncestryChanged:Connect(function()
  672.                     if ObjectFrame.Parent == nil then
  673.                         cached:Disconnect();
  674.                     end
  675.                 end)
  676.  
  677.                 switch.Interact.MouseButton1Down:Connect(function()
  678.                     Data.Spying = not Data.Spying;
  679.                     toggle_switch(Data.Spying)
  680.                 end)
  681.  
  682.                 ObjectFrame.Parent = Panels["List"];
  683.             end
  684.  
  685.             local function PopulateObject(Remote, Data)
  686.                 local ObjectFrame = CreateObjectTemplate(Templates.Object, Remote)
  687.                 local FireAmount = ObjectFrame.Label.amount;
  688.                 local Clear_Cache = ObjectFrame.Clear;
  689.                 local thisRemoteColor = self.RemoteColors[Remote.ClassName];
  690.  
  691.                 ObjectFrame.Emblem.ImageColor3 = thisRemoteColor
  692.                 Clear_Cache.BackgroundColor3 = thisRemoteColor;
  693.                 Clear_Cache.Font = "SourceSansBold"
  694.                 FireAmount.Text = tostring(Data.FireCount)
  695.  
  696.                 Clear_Cache.MouseButton1Down:Connect(function()
  697.                     self:ClearCacheData(Remote);
  698.                     ObjectFrame:Destroy();
  699.                 end)
  700.  
  701.                 Data.Updated.Event:Connect(function(Operation)
  702.                     if FireAmount and Operation ~= "SpyChange" then
  703.                         FireAmount.Text = Data.FireCount;
  704.                     end
  705.                 end)
  706.  
  707.                 ObjectFrame.Parent = Panels["View"];
  708.                 return FireAmount;
  709.             end
  710.  
  711.             local function PopulateHttpObject(Type, Data)
  712.                 local ObjectFrame = CreateObjectTemplate(Templates.Object, Type)
  713.                 local FireAmount = ObjectFrame.Label.amount;
  714.                 local Clear_Cache = ObjectFrame.Clear;
  715.  
  716.                 local thisReqColor = self.HttpColors[Type];
  717.  
  718.                 ObjectFrame.Emblem.ImageColor3 = thisReqColor;
  719.                 Clear_Cache.BackgroundColor3 = thisReqColor;
  720.                 Clear_Cache.Font = "SourceSansBold"
  721.                 FireAmount.Text = tostring(Data.FireCount)
  722.  
  723.                 Clear_Cache.MouseButton1Down:Connect(function()
  724.                     print(Type)
  725.                     self:ClearRequestCache(Type);
  726.                     ObjectFrame:Destroy();
  727.                 end)
  728.  
  729.                 Data.Updated.Event:Connect(function(Operation)
  730.                     if FireAmount and Operation ~= "SpyChange" then
  731.                         FireAmount.Text = Data.FireCount;
  732.                     end
  733.                 end)
  734.  
  735.                 ObjectFrame.Parent = Panels["View"];
  736.                 return FireAmount;
  737.             end
  738.  
  739.             local function PopulateObjects(Type)
  740.                 for _,OldObject in pairs(Panels["View"]:GetChildren()) do
  741.                     if OldObject:IsA("Frame") then
  742.                         OldObject:Destroy();
  743.                     end
  744.                 end
  745.  
  746.                 local NumObjects = 0;
  747.                 for Remote,Data in pairs(self.Cache) do
  748.                     if tostring(Remote) ~= "_entry" and Remote.ClassName == Type and Data.FireCount > 0 then
  749.                         PopulateObject(Remote, Data);
  750.                         NumObjects = NumObjects + 1;
  751.                     end
  752.                 end
  753.  
  754.                 Panels["View"].CanvasSize = UDim2.new(0,0,0,20*NumObjects)
  755.                 Panels["View"].CanvasPosition = Vector2.new();
  756.             end
  757.  
  758.             local function PopulateHttpObjects(Type)
  759.                 for _,OldObject in pairs(Panels["View"]:GetChildren()) do
  760.                     if OldObject:IsA("Frame") then
  761.                         OldObject:Destroy();
  762.                     end
  763.                 end
  764.  
  765.                 local NumObjects = 0;
  766.                 for Req,Data in pairs(self.HttpCache) do
  767.                     if Req ~= "_entry" and Req == Type and Data.FireCount > 0 then
  768.                         PopulateHttpObject(Req, Data);
  769.                         NumObjects = NumObjects + 1;
  770.                     end
  771.                 end
  772.  
  773.                 Panels["View"].CanvasSize = UDim2.new(0,0,0,20*NumObjects)
  774.                 Panels["View"].CanvasPosition = Vector2.new();
  775.             end
  776.  
  777.             local function PopulateListObjects(Type)
  778.                 for _,OldObject in pairs(Panels["List"]:GetChildren()) do
  779.                     if OldObject:IsA("Frame") then
  780.                         OldObject:Destroy();
  781.                     end
  782.                 end
  783.  
  784.                 local NumObjects = 0;
  785.                 for Remote,Data in pairs(self.Cache) do
  786.                     if tostring(Remote) ~= "_entry" and Remote.ClassName == Type then
  787.                         PopulateObject2(Remote, Data);
  788.                         NumObjects = NumObjects + 1;
  789.                     end
  790.                 end
  791.  
  792.                 Panels["List"].CanvasSize = UDim2.new(0,0,0,20*NumObjects)
  793.                 Panels["List"].CanvasPosition = Vector2.new();
  794.             end
  795.  
  796.             local function PopulateHttpListObjects(Type)
  797.                 for _,OldObject in pairs(Panels["List"]:GetChildren()) do
  798.                     if OldObject:IsA("Frame") then
  799.                         OldObject:Destroy();
  800.                     end
  801.                 end
  802.  
  803.                 local NumObjects = 0;
  804.                 for Req,Data in pairs(self.HttpCache) do
  805.                     if Req ~= "_entry" and Req == Type then
  806.                         PopulateHttpObject2(Req, Data);
  807.                         NumObjects = NumObjects + 1;
  808.                     end
  809.                 end
  810.             end
  811.  
  812.             local function CallDropdown(remote, string_func, varargs)
  813.                 if Spy:FindFirstChild("CallDropdown") then
  814.                     Spy.Call_Dropdown:Destroy();
  815.                 end
  816.                 local this_dropdown = Templates.CallDropdown:Clone();
  817.                 this_dropdown.Position = UDim2.new(0,Mouse.X - 5,0,Mouse.Y - 5)
  818.  
  819.                 this_dropdown.MouseLeave:Connect(function()
  820.                     if HoveringCallData.object == remote or HoveringCallData.varargs == varargs then
  821.                         HoveringCallData.object = nil;
  822.                         HoveringCallData.varargs = nil;
  823.                     end
  824.                     this_dropdown:Destroy();
  825.                 end)
  826.  
  827.                 local Call = this_dropdown.CallAgain;
  828.                 local GenerateScript = this_dropdown.GenScript;
  829.  
  830.                 Call.MouseButton1Down:Connect(function()
  831.                     local func = remote[self.RemoteFuncRef[remote.ClassName]];
  832.                     if func then
  833.                         pcall(function()
  834.                             func(remote, unpack(varargs));
  835.                         end);
  836.                     end
  837.                 end)
  838.  
  839.                 GenerateScript.MouseButton1Down:Connect(function()
  840.                     local Code = FrostHook.ScriptGeneration.AppendBeginning;
  841.                     local Variables,Cache = {},{table=0,number=0,userdata=0,string=0,boolean=0};
  842.  
  843.                     for i,v in pairs(varargs) do
  844.                         local var, new_Cache = FrostHook.ScriptGeneration:var_name(Cache, v);
  845.                         local RefValue = FrostHook.ScriptGeneration:transform_value(v)
  846.                         Cache = new_Cache;
  847.  
  848.                         table.insert(Variables, {
  849.                             Variable = var,
  850.                             Value =  RefValue,
  851.                         })
  852.                     end
  853.  
  854.                     table.insert(Variables, {
  855.                         Variable = "Target",
  856.                         Value = FrostHook.ScriptGeneration:transform_value(remote);
  857.                     })
  858.  
  859.                     for _,data in next, Variables do
  860.                         Code = Code.."local "..data.Variable.." = "..data.Value..";\n";
  861.                     end
  862.  
  863.                     Code = Code.."Target:"..string_func.."("
  864.  
  865.                     local ArrayVars = {};
  866.  
  867.                     for _,data in pairs(Variables) do
  868.                         if data.Variable ~= "Target" then
  869.                             table.insert(ArrayVars, data.Variable)
  870.                         end
  871.                     end
  872.  
  873.                     Code = Code..table.concat(ArrayVars, ", ")
  874.                     Code = Code..");";
  875.                     Code = Code..FrostHook.ScriptGeneration.AppendEnding;
  876.                     FrostHook.TextEditor:SetCode(Code);
  877.                 end)
  878.  
  879.                 this_dropdown.Visible = true;
  880.                 this_dropdown.Parent = Spy;
  881.             end
  882.  
  883.             local function HTTPCallDropdown(reqtype, varargs)
  884.                 if Spy:FindFirstChild("CallDropdown") then
  885.                     Spy.Call_Dropdown:Destroy();
  886.                 end
  887.                 local this_dropdown = Templates.CallDropdown:Clone();
  888.                 this_dropdown.Position = UDim2.new(0,Mouse.X - 5,0,Mouse.Y - 5)
  889.  
  890.                 this_dropdown.MouseLeave:Connect(function()
  891.                     if HoveringCallData.object == remote or HoveringCallData.varargs == varargs then
  892.                         HoveringCallData.object = nil;
  893.                         HoveringCallData.varargs = nil;
  894.                     end
  895.                     this_dropdown:Destroy();
  896.                 end)
  897.  
  898.                 local Call = this_dropdown.CallAgain;
  899.                 local GenerateScript = this_dropdown.GenScript;
  900.  
  901.                 Call.MouseButton1Down:Connect(function()
  902.                     local func = game[reqtype];
  903.                     if func then
  904.                         pcall(function()
  905.                             func(remote, unpack(varargs));
  906.                         end);
  907.                     end
  908.                 end)
  909.  
  910.                 GenerateScript.MouseButton1Down:Connect(function()
  911.                     local Code = FrostHook.ScriptGeneration.AppendBeginning;
  912.                     local Variables,Cache = {},{table=0,number=0,userdata=0,string=0,boolean=0};
  913.  
  914.                     for i,v in pairs(varargs) do
  915.                         local var, new_Cache = FrostHook.ScriptGeneration:var_name(Cache, v);
  916.                         local RefValue = FrostHook.ScriptGeneration:transform_value(v)
  917.                         Cache = new_Cache;
  918.  
  919.                         table.insert(Variables, {
  920.                             Variable = var,
  921.                             Value =  RefValue,
  922.                         })
  923.                     end
  924.  
  925.                     for _,data in next, Variables do
  926.                         Code = Code.."local "..data.Variable.." = "..data.Value..";\n";
  927.                     end
  928.  
  929.                     Code = Code.."game:"..reqtype.."("
  930.  
  931.                     local ArrayVars = {};
  932.  
  933.                     for _,data in pairs(Variables) do
  934.                         if data.Variable ~= "Target" then
  935.                             table.insert(ArrayVars, data.Variable)
  936.                         end
  937.                     end
  938.  
  939.                     Code = Code..table.concat(ArrayVars, ", ")
  940.                     Code = Code..");";
  941.                     Code = Code..FrostHook.ScriptGeneration.AppendEnding;
  942.                     FrostHook.TextEditor:SetCode(Code);
  943.                 end);
  944.  
  945.                 this_dropdown.Visible = true;
  946.                 this_dropdown.Parent = Spy;
  947.             end
  948.            
  949.             local function ViewCalls(Object)
  950.                 local ReadingNewCalls = true;
  951.                 local Data = self.HttpCache[Object] or self.Cache[Object];
  952.  
  953.                 if not(Data) then
  954.                     print("Denied")
  955.                     return;
  956.                 end
  957.  
  958.                 local this_callview = Templates.CallView:Clone();
  959.                 local main = this_callview.Main;
  960.                 local buttons = main.Topbar_shadow.TopbarButtons
  961.                 local CallFrame = main.Calls;
  962.  
  963.                 local Hook_FuncRef = self.RemoteFuncRef;
  964.  
  965.                 local _info = TweenInfo.new(0.2,Enum.EasingStyle.Quad,Enum.EasingDirection.Out,0,false,0)
  966.  
  967.                 local function PreviewCall(array)
  968.                     local this_Call = ExampleCall:Clone();
  969.  
  970.                     if #array <= 0 then
  971.                         this_Call.Expand.Visible = false;
  972.                     end
  973.                    
  974.                     local ArgDataTypes = {}
  975.                     local StateImages = {
  976.                         [true] = "rbxassetid://4317834259",
  977.                         [false] = "rbxassetid://4317835953"
  978.                     }
  979.                     local Expanded = false;
  980.                     local _select = game:GetService("TweenService"):Create(this_Call, _info, {["BackgroundColor3"]=Color3.new(0.5,0.5,0.5)})
  981.                     local _unselect = game:GetService("TweenService"):Create(this_Call, _info, {["BackgroundColor3"]=Color3.new(0,0,0)})
  982.  
  983.                     for i,v in pairs(array) do
  984.                         if tostring(typeof(v)) == "nil" then
  985.                             array[i] = "nil";
  986.                         end
  987.                     end
  988.  
  989.                     for i=1,#array do
  990.                         local arg = array[i];
  991.                         table.insert(ArgDataTypes, typeof(arg))
  992.                         local add_Data = this_Call.Templates["AdditionalData"]:Clone();
  993.                         local data_color,formatted_data = self:DatatypeFormat(arg)
  994.                         add_Data.Data.Text = formatted_data;
  995.                         add_Data.ImageLabel.ImageColor3 = data_color;
  996.                         add_Data.Visible = true;
  997.                         add_Data.Parent = this_Call.Additional;
  998.                     end
  999.  
  1000.                     this_Call.CallType.Text = tostring((type(Object)=="string" and Object or Hook_FuncRef[Object.ClassName]) ).."("..table.concat(ArgDataTypes, ", ")..")";
  1001.  
  1002.                     this_Call.MouseEnter:Connect(function()
  1003.                         HoveringCallData.object = Object;
  1004.                         HoveringCallData.varargs = array;
  1005.                         _select:Play();
  1006.                     end)
  1007.  
  1008.                     this_Call.MouseLeave:Connect(function()
  1009.                         _unselect:Play();
  1010.                     end)
  1011.  
  1012.                     this_Call.Expand.MouseButton1Down:Connect(function()
  1013.                         Expanded = not Expanded;
  1014.                         this_Call.Expand.Image = StateImages[Expanded];
  1015.                         if Expanded then
  1016.                             this_Call:TweenSize(UDim2.new(1,0,0,20 + 22*#array), "Out", "Quad", 0.2, true, function()
  1017.                                 CallFrame.CanvasSize = UDim2.new(0,0,0,CallFrame.CanvasSize.Y.Offset+(#array*22));
  1018.                             end);
  1019.                         else
  1020.                             this_Call:TweenSize(UDim2.new(1,0,0,20), "Out", "Quad", 0.2, true, function()
  1021.                                 CallFrame.CanvasSize = UDim2.new(0,0,0,CallFrame.CanvasSize.Y.Offset-(#array*22));
  1022.                             end);
  1023.                         end
  1024.                     end)
  1025.  
  1026.                     this_Call.Visible = true;
  1027.                     CallFrame.CanvasSize = UDim2.new(0,0,0,CallFrame.CanvasSize.Y.Offset+20);
  1028.                     this_Call.Parent = CallFrame;
  1029.                 end
  1030.  
  1031.                 for i=1,#Data.Logs do
  1032.                     PreviewCall(Data.Logs[i]);
  1033.                 end
  1034.  
  1035.                 self.CustomDrag:SetDragging(true, this_callview, main);
  1036.                
  1037.                 buttons.Close.MouseButton1Down:Connect(function()
  1038.                     self.CustomDrag:SetDragging(false, this_callview, main);
  1039.                     this_callview:Destroy();
  1040.                 end)
  1041.                
  1042.                 buttons.Export.MouseButton1Down:Connect(function()
  1043.                     self.env.to_clipboard(self.ScriptGeneration:dump_table(Data.Logs))
  1044.                 end)
  1045.  
  1046.                 if Data.Spying then
  1047.                     buttons.Play.Visible = false;
  1048.                     buttons.Stop.Visible = true;
  1049.                 else
  1050.                     buttons.Play.Visible = true;
  1051.                     buttons.Play.Visible = false;
  1052.                 end
  1053.                
  1054.                 buttons.Play.MouseButton1Down:Connect(function()
  1055.                     Data.Spying = true;
  1056.                     Data.Updated:Fire("SpyChange")
  1057.                     buttons.Stop.Visible = true;
  1058.                     buttons.Play.Visible = false;
  1059.                 end)
  1060.                
  1061.                 buttons.Stop.MouseButton1Down:Connect(function()
  1062.                     Data.Spying = false;
  1063.                     Data.Updated:Fire("SpyChange")
  1064.                     buttons.Stop.Visible = false;
  1065.                     buttons.Play.Visible = true;
  1066.                 end)
  1067.  
  1068.                 CallFrame.MouseLeave:Connect(function()
  1069.                     HoveringCallData.object = nil;
  1070.                     HoveringCallData.varargs = nil;
  1071.                 end)
  1072.  
  1073.                 Data.Updated.Event:Connect(function(Operation, varargs)
  1074.                     if Operation == "Add" then
  1075.                         PreviewCall(varargs);
  1076.                     elseif Operation == "Clear" then
  1077.                         for _,Object in pairs(CallFrame:GetChildren()) do
  1078.                             if Object.ClassName == "Frame" or Object.ClassName == "ScrollingFrame" then
  1079.                                 Object:Destroy();
  1080.                             end
  1081.                         end
  1082.                         CallFrame.CanvasSize = UDim2.new(0,0,0,0);
  1083.                     end
  1084.                 end)
  1085.  
  1086.                 self:SetTooltip(buttons.Stop, "Stop")
  1087.                 self:SetTooltip(buttons.Play, "Start")
  1088.                 self:SetTooltip(buttons.Export, "Export Calls")
  1089.                 self:SetTooltip(buttons.Close, "Close window")
  1090.                
  1091.                 main.Topbar_shadow.Viewing.Text = tostring(Object);
  1092.                 this_callview.Visible = true;
  1093.                 this_callview.Parent = Spy;
  1094.             end
  1095.            
  1096.             local function Dropdown(Object)
  1097.                 if Spy:FindFirstChild("Dropdown") then
  1098.                     Spy.Dropdown:Destroy();
  1099.                 end
  1100.                 local this_dropdown = Templates.Dropdown:Clone();
  1101.                 this_dropdown.Position = UDim2.new(0,Mouse.X - 5,0,Mouse.Y - 5)
  1102.                 this_dropdown.Visible = true;
  1103.                 this_dropdown.Parent = Spy;
  1104.                
  1105.                 this_dropdown.MouseLeave:Connect(function()
  1106.                     this_dropdown:Destroy();
  1107.                 end)
  1108.                
  1109.                 local CallView = this_dropdown.Calls;
  1110.                 local GetPath = this_dropdown.GetPath;
  1111.                
  1112.                 GetPath.MouseButton1Down:Connect(function()
  1113.                     if type(Object) == "string" then
  1114.                         FrostHook.env.to_clipboard("game:"..Object.."()")
  1115.                     else
  1116.                         FrostHook.env.to_clipboard(FrostHook.ScriptGeneration:transform_path(Object:GetFullName()))
  1117.                     end
  1118.                 end)
  1119.                
  1120.                 CallView.MouseButton1Down:Connect(function()
  1121.                     ViewCalls(Object);
  1122.                 end)
  1123.             end
  1124.            
  1125.             local function ViewTab(tab_name)
  1126.                 for _,Tab in pairs(Tabs) do
  1127.                     if Tab.Name == tab_name then
  1128.                         Tab.BackgroundTransparency = 1;
  1129.                     else
  1130.                         Tab.BackgroundTransparency = 0.8;
  1131.                     end
  1132.                 end
  1133.                
  1134.                 SearchBar.Visible = (tab_name=="List")and true or false;
  1135.                 ExecuteButton.Visible = (tab_name=="Code")and true or false;
  1136.            
  1137.                 for PanName,Panel in pairs(Panels) do
  1138.                     if PanName == tab_name then
  1139.                         Panel.Visible = true;
  1140.                     else
  1141.                         Panel.Visible = false;
  1142.                     end
  1143.                 end
  1144.             end
  1145.  
  1146.             local function fixCanvas_View()
  1147.                 if FrostHook and not AddRemoveOverride then
  1148.                     Panels["View"].CanvasSize = UDim2.new(0,0,0,20*#(Panels["View"]:GetChildren())-1)
  1149.                     Panels["List"].CanvasSize = UDim2.new(0,0,0,20*#(Panels["List"]:GetChildren())-1)
  1150.                 end
  1151.             end
  1152.  
  1153.             for _,Directory in pairs(self.Search_Directories) do -- Populates the Cache full of every remote/bindable in the game.
  1154.                 for _,Obj in pairs(Directory:GetDescendants()) do
  1155.                     local Class = Obj.ClassName;
  1156.                     if Class == "RemoteEvent" or Class == "RemoteFunction" or Class == "BindableEvent" or Class == "BindableFunction" then
  1157.                         self:CacheData(Obj,nil,true);
  1158.                     end
  1159.                 end
  1160.             end
  1161.  
  1162.             for _,Obj in pairs(TabPanel:GetChildren()) do -- Populates the Tabs
  1163.                 if Obj:IsA("TextButton") or Obj.Name == "Space" then
  1164.                     Tabs[Obj.Name] = Obj;
  1165.                     if Obj:IsA("TextButton") then
  1166.                         Obj.MouseButton1Down:Connect(function()
  1167.                             ViewTab(Obj.Name);
  1168.                         end)
  1169.                     end
  1170.                 end
  1171.             end
  1172.            
  1173.             for _,Obj in pairs(MainPanel:GetChildren()) do -- Populates the Panels
  1174.                 if Obj:IsA("ScrollingFrame") then
  1175.                     Panels[Obj.Name] = Obj;
  1176.                 end
  1177.             end
  1178.            
  1179.             for _,Obj in pairs(Main.SidePanel:GetChildren()) do -- Populates the Sub-Categories.
  1180.                 if Obj:IsA("Frame") then
  1181.                     Categories[Obj.Name] = {["Object"] = Obj, ["ResetAllAmounts"] = false, ["SubOptions"] = false, ["_init"] = false};
  1182.                 end
  1183.             end
  1184.  
  1185.             local ForceUnset = Instance.new("BindableEvent");
  1186.             ForceUnset.Name = "Force-Unset"
  1187.             self.Internal_Ignored[ForceUnset] = true;
  1188.        
  1189.             for CatName,CatObj in pairs(Categories) do
  1190.                 local Content = CatObj.Object.Content;
  1191.                 local expand = Content.expand;
  1192.                 local CatFireAmount = Content.amount;
  1193.                 local State = false;
  1194.                 local StateImages = {
  1195.                     [true] = "rbxassetid://4317834259",
  1196.                     [false] = "rbxassetid://4317835953"
  1197.                 }
  1198.                
  1199.                 local SubOptions = {_len=0};
  1200.  
  1201.                 self.FireCounts._updated.Event:Connect(function()
  1202.                     if CatName == "Remotes" then
  1203.                         local EventAmount = self.FireCounts["RemoteEvent"];
  1204.                         local FunctionAmount = self.FireCounts["RemoteFunction"];
  1205.                         CatFireAmount.Text = tostring(EventAmount + FunctionAmount)
  1206.                     elseif CatName == "Bindables" then
  1207.                         local EventAmount = self.FireCounts["BindableEvent"];
  1208.                         local FunctionAmount = self.FireCounts["BindableFunction"];
  1209.                         CatFireAmount.Text = tostring(EventAmount + FunctionAmount)
  1210.                     elseif CatName == "HTTP" then
  1211.                         local GetAmount = self.FireCounts["HttpGet"];
  1212.                         local PostAmount = self.FireCounts["HttpPost"];
  1213.                         local GetObjAmount = self.FireCounts["GetObjects"];
  1214.                         CatFireAmount.Text = tostring(GetAmount + PostAmount + GetObjAmount);
  1215.                     end
  1216.                 end)
  1217.                
  1218.                 for _,Obj in pairs(CatObj.Object:GetChildren()) do
  1219.                     if Obj:IsA("TextButton") then
  1220.                         SubOptions._len = SubOptions._len + 1;
  1221.                        
  1222.                         local TypeRef = CatName=="HTTP" and (Obj.Name=="GetObjects" and "GetObjects" or "Http"..Obj.Name) or Obj:FindFirstChild("_type")
  1223.                         local FireAmount = Obj.amount;
  1224.                         local Selected = false;
  1225.  
  1226.                         self.FireCounts._updated.Event:Connect(function()
  1227.                             if TypeRef then
  1228.                                 if CatName == "HTTP" then
  1229.                                     local MyCount = self.FireCounts[(Obj.Name=="GetObjects" and "GetObjects" or "Http"..Obj.Name)];
  1230.                                     FireAmount.Text = MyCount;
  1231.                                 else
  1232.                                     local MyCount = self.FireCounts[TypeRef.Value];
  1233.                                     FireAmount.Text = MyCount;
  1234.                                 end
  1235.                             end
  1236.                         end)
  1237.                        
  1238.                         SubOptions[Obj.Name] = {["Object"] = Obj};
  1239.                        
  1240.                         local _info = TweenInfo.new(0.2,Enum.EasingStyle.Quad,Enum.EasingDirection.Out,0,false,0)
  1241.                         local _select = game:GetService("TweenService"):Create(Obj, _info, {["BackgroundTransparency"]=0.9})
  1242.                         local _unselect = game:GetService("TweenService"):Create(Obj, _info, {["BackgroundTransparency"]=1})
  1243.                         local _setcat = game:GetService("TweenService"):Create(Obj, _info, {["BackgroundColor3"]=Color3.new(85/255, 170/255, 1)})
  1244.                         local _unsetcat = game:GetService("TweenService"):Create(Obj, _info, {["BackgroundColor3"]=Color3.new(120/255, 120/255, 120/255)})
  1245.                        
  1246.                         Obj.MouseEnter:Connect(function()
  1247.                             if not(Selected) then
  1248.                                 _select:Play();
  1249.                             end
  1250.                         end)
  1251.                        
  1252.                         Obj.MouseLeave:Connect(function()
  1253.                             if not(Selected) then
  1254.                                 _unselect:Play()
  1255.                             end
  1256.                         end)
  1257.  
  1258.                         ForceUnset.Event:Connect(function(selector)
  1259.                             if selector == Obj then
  1260.                                 Selected = true;
  1261.                                 return
  1262.                             end
  1263.                             Selected = false;
  1264.                             _unsetcat:Play();
  1265.                             _unselect:Play();
  1266.                         end)
  1267.                        
  1268.                         Obj.MouseButton1Down:Connect(function()
  1269.                             if TypeRef and CatName ~= "HTTP" then
  1270.                                 ForceUnset:Fire(Obj);
  1271.                                 _select:Play();
  1272.                                 _setcat:Play();
  1273.                                 ViewingType = tostring(TypeRef.Value)
  1274.                                 AddRemoveOverride = true;
  1275.                                 PopulateObjects(TypeRef.Value);
  1276.                                 PopulateListObjects(TypeRef.Value);
  1277.                                 AddRemoveOverride = false;
  1278.                             else
  1279.                                 ForceUnset:Fire(Obj);
  1280.                                 _select:Play();
  1281.                                 _setcat:Play();
  1282.                                 ViewingType = tostring(TypeRef)
  1283.                                 AddRemoveOverride = true;
  1284.                                 PopulateHttpObjects(TypeRef);
  1285.                                 PopulateHttpListObjects(TypeRef);
  1286.                                 AddRemoveOverride = false;
  1287.                             end
  1288.                         end)
  1289.                     end
  1290.                 end
  1291.                
  1292.                 Categories[CatName].SubOptions = SubOptions;
  1293.                 Categories[CatName].ResetAllAmounts = CategoryResetAllAmounts;
  1294.                 Categories[CatName]._init = true;
  1295.                
  1296.                 expand.MouseButton1Down:Connect(function()
  1297.                     State = not State;
  1298.                     expand.Image = StateImages[State];
  1299.                     if State then
  1300.                         CatObj.Object:TweenSize(UDim2.new(1,0,0,20*(SubOptions._len+1)), "Out", "Quad", 0.25, true)
  1301.                     else
  1302.                         CatObj.Object:TweenSize(UDim2.new(1,0,0,20), "Out", "Quad", 0.25, true)
  1303.                     end
  1304.                 end)
  1305.             end
  1306.  
  1307.             self:RegisterConnection(self.FireCounts._latest.Event, function(remote)
  1308.                 if type(remote) == "string" then -- HTTP
  1309.                     if ViewingType == remote then
  1310.                         if not(Panels["View"]:FindFirstChild(remote)) then
  1311.                             PopulateHttpObject(remote, self.HttpCache[remote]);
  1312.                         elseif not(Panels["List"]:FindFirstChild(remote)) then
  1313.                             PopulateHttpObject2(remote, self.HttpCache[remote]);
  1314.                         end
  1315.                     end
  1316.                 else -- REMOTE
  1317.                     if ViewingType == tostring(remote.ClassName) then
  1318.                         if not(Panels["View"]:FindFirstChild(remote.Name)) then
  1319.                             PopulateObject(remote, self.Cache[remote])
  1320.                         elseif not(Panels["List"]:FindFirstChild(remote.Name)) then
  1321.                             PopulateObject2(remote, self.Cache[remote])
  1322.                         end
  1323.                     end
  1324.                 end
  1325.             end)
  1326.  
  1327.             self:RegisterConnection(Panels["View"].ChildAdded, fixCanvas_View)
  1328.             self:RegisterConnection(Panels["View"].ChildRemoved, fixCanvas_View)
  1329.  
  1330.             self:RegisterConnection(OpenButton.MouseButton1Down, function()
  1331.                 OpenButton.Parent.Visible = false;
  1332.                 topbar.Visible = true;
  1333.             end)
  1334.  
  1335.             self:RegisterConnection(CloseButton.MouseButton1Down, function()
  1336.                 OpenButton.Parent.Visible = true;
  1337.                 topbar.Visible = false;
  1338.             end)
  1339.  
  1340.             self:RegisterConnection(DestroyButton.MouseButton1Down, function()
  1341.                 self:Destroy();
  1342.             end)
  1343.  
  1344.             self:RegisterConnection(SearchBar.FocusLost, function()
  1345.                 if SearchBar.Text == "" then
  1346.                     SearchBar.Close.Visible = false;
  1347.                 end
  1348.             end)
  1349.            
  1350.             self:RegisterConnection(SearchBar.Close.MouseButton1Down, function()
  1351.                 SearchBar:ReleaseFocus(false);
  1352.                 SearchBar.Text = "";
  1353.                 SearchBar.Close.Visible = false;
  1354.                 fixCanvas_View();
  1355.                 for _,Object in pairs(Panels["List"]:GetChildren()) do
  1356.                     if Object:IsA("Frame") then
  1357.                         Object.Visible = true;
  1358.                     end
  1359.                 end
  1360.             end)
  1361.  
  1362.             self:RegisterConnection(ExecuteButton.MouseButton1Down, function()
  1363.                 local CodeText = Panels["Code"].Main.Input.Text or "";
  1364.                 if self.TextEditor.Imported then
  1365.                     CodeText = self.TextEditor:RevertTabs(CodeText);
  1366.                 end
  1367.  
  1368.                 local success,error = pcall(function()
  1369.                     spawn(loadstring(CodeText)() or function()end)
  1370.                 end)
  1371.  
  1372.                 local OldColor = ExecuteButton.BackgroundColor3;
  1373.  
  1374.                 if success then
  1375.                     print("Execute Error: ", error);
  1376.                 end
  1377.             end)
  1378.  
  1379.             self:RegisterConnection(self.Services.UserInputService.InputBegan, function(inputObject)
  1380.                 local InputType = inputObject.UserInputType;
  1381.                 if InputType == Enum.UserInputType.MouseButton2 then
  1382.                     if HoveringObject then
  1383.                         Dropdown(HoveringObject)
  1384.                     end
  1385.                     if HoveringCallData.object and HoveringCallData.varargs then
  1386.                         if type(HoveringCallData.object) == "string" then
  1387.                             HTTPCallDropdown(HoveringCallData.object, HoveringCallData.varargs);
  1388.                         else
  1389.                             CallDropdown(HoveringCallData.object, self.RemoteFuncRef[HoveringCallData.object.ClassName], HoveringCallData.varargs);
  1390.                         end
  1391.                     end
  1392.                 end
  1393.             end)
  1394.  
  1395.             self.CustomDrag:SetDragging(true, topbar, Main);
  1396.             self.CustomDrag:SetResizing(true, topbar, Main, drag);
  1397.             ViewTab(CurrentTab);
  1398.  
  1399.             self:RegisterConnection(self.Services.RunService.RenderStepped, function()
  1400.                 if SearchBar.Text ~= "" and SearchBar.Close.Visible == false then
  1401.                     SearchBar.Close.Visible = true
  1402.                 end
  1403.                
  1404.                 if SearchBar.Text ~= "" then
  1405.                     for _,Object in pairs(Panels["List"]:GetChildren()) do
  1406.                         local Visible_Objects = 0;
  1407.                         if Object:IsA("Frame") then
  1408.                             if Object.Name:lower():find(SearchBar.Text:lower()) then
  1409.                                 Visible_Objects = Visible_Objects + 1;
  1410.                                 Object.Visible = true;
  1411.                             else
  1412.                                 Object.Visible = false;
  1413.                             end
  1414.                         end
  1415.                         Panels["List"].CanvasSize = UDim2.new(0,0,0,20*Visible_Objects)
  1416.                     end
  1417.                 end
  1418.  
  1419.                 if tooltip.Visible then
  1420.                     tooltip.Position = UDim2.new(0,Mouse.X + 5,0,Mouse.Y - tooltip.AbsoluteSize.Y)
  1421.                 end
  1422.             end)
  1423.  
  1424.             do -- Lines
  1425.                 local function CreateFadedLineH(holder)
  1426.                     local globtrans = 0
  1427.                     holder.BackgroundTransparency = 1;
  1428.                     for i=holder.AbsoluteSize.X/2,holder.AbsoluteSize.X,1 do
  1429.                         globtrans = globtrans + (1/(holder.AbsoluteSize.X/2))
  1430.                         local p = Instance.new("Frame", holder)
  1431.                         p.Size = UDim2.new(0,1,1,0)
  1432.                         p.BorderSizePixel = 0;
  1433.                         p.Parent = holder
  1434.                         p.BackgroundColor3 = holder.BackgroundColor3
  1435.                         p.Position = UDim2.new(0,i,0,0)
  1436.                         p.BackgroundTransparency = globtrans
  1437.                     end
  1438.                     globtrans = 1
  1439.                     for i=0,holder.AbsoluteSize.X/2,1 do
  1440.                         globtrans = globtrans - (1/(holder.AbsoluteSize.X/2))
  1441.                         local p = Instance.new("Frame", holder)
  1442.                         p.Size = UDim2.new(0,1,1,0)
  1443.                         p.BorderSizePixel = 0;
  1444.                         p.Parent = holder
  1445.                         p.BackgroundColor3 = holder.BackgroundColor3
  1446.                         p.Position = UDim2.new(0,i,0,0)
  1447.                         p.BackgroundTransparency = globtrans
  1448.                     end
  1449.                 end
  1450.                
  1451.                 local function CreateFadedLineV(holder)
  1452.                     local globtrans = 0
  1453.                     holder.BackgroundTransparency = 1;
  1454.                     for i=holder.AbsoluteSize.Y/2,holder.AbsoluteSize.Y,1 do
  1455.                         globtrans = globtrans + (1/(holder.AbsoluteSize.Y/2))
  1456.                         local p = Instance.new("Frame", holder)
  1457.                         p.Size = UDim2.new(1,0,0,1)
  1458.                         p.BorderSizePixel = 0;
  1459.                         p.Parent = holder
  1460.                         p.BackgroundColor3 = holder.BackgroundColor3
  1461.                         p.Position = UDim2.new(0,0,0,i)
  1462.                         p.BackgroundTransparency = globtrans
  1463.                     end
  1464.                     globtrans = 1
  1465.                     for i=0,holder.AbsoluteSize.Y/2,1 do
  1466.                         globtrans = globtrans - (1/(holder.AbsoluteSize.Y/2))
  1467.                         local p = Instance.new("Frame", holder)
  1468.                         p.Size = UDim2.new(1,0,0,1)
  1469.                         p.BorderSizePixel = 0;
  1470.                         p.Parent = holder
  1471.                         p.BackgroundColor3 = holder.BackgroundColor3
  1472.                         p.Position = UDim2.new(0,0,0,i)
  1473.                         p.BackgroundTransparency = globtrans
  1474.                     end
  1475.                 end
  1476.                
  1477.                 for _, obj in next, Spy:GetDescendants() do
  1478.                     if obj.Name == "HorizontalLine" then
  1479.                         CreateFadedLineH(obj);
  1480.                     end
  1481.                 end
  1482.                 for _, obj in next, Spy:GetDescendants() do
  1483.                     if obj.Name == "VerticalLine" then
  1484.                         CreateFadedLineV(obj);
  1485.                     end
  1486.                 end
  1487.             end
  1488.         end
  1489.  
  1490.         self.TextEditor();
  1491.         self.TextEditor:SetCode("");
  1492.         self.CustomDrag();
  1493.  
  1494.         self:TrackRemotes(); -- Start tracking all remotes
  1495.         self:TrackHttp(); -- Start tracking all http requests
  1496.     end
  1497.     setmetatable(FrostHook, metadata);
  1498. end
  1499.  
  1500. do -- Custom Dragging/Resizing object.
  1501.     local metadata = {};
  1502.     local Cached_ResizeConnections = {};
  1503.     local Cached_DragConnections = {};
  1504.     local methods = {
  1505.         SetDragging = function(self, toggle, frame, main)
  1506.             if toggle then
  1507.                 if Cached_DragConnections[frame] then
  1508.                     return;
  1509.                 end
  1510.  
  1511.                 self.DragActive[frame] = {
  1512.                     ["Main"] = main,
  1513.                     Dragging = false,
  1514.                     MouseOnTopBar = false,
  1515.                     startPosition = Vector2.new(),
  1516.                     TopbarPosition = Vector2.new(),
  1517.                 };
  1518.  
  1519.                 local mE = frame.MouseEnter:Connect(function()
  1520.                     self.DragActive[frame].MouseOnTopBar = true;
  1521.                 end)
  1522.  
  1523.                 local mL = frame.MouseLeave:Connect(function()
  1524.                     self.DragActive[frame].MouseOnTopBar = false;
  1525.                 end)
  1526.  
  1527.                 Cached_DragConnections[frame] = {mE,mL};
  1528.             else
  1529.                 for obj,cons in pairs(Cached_DragConnections) do
  1530.                     if obj == frame then
  1531.                         for _,con in pairs(cons) do
  1532.                             con:Disconnect();
  1533.                         end
  1534.                     end
  1535.                 end
  1536.                 self.DragActive[frame] = nil;
  1537.             end
  1538.         end,
  1539.         SetResizing = function(self, toggle, frame, main, dragbtn)
  1540.             if toggle then
  1541.                 if self.ResizeActive[frame] then
  1542.                     return;
  1543.                 end
  1544.                 self.ResizeActive[frame] = {
  1545.                     ["Main"] = main,
  1546.                     Resizing = false,
  1547.                     startPosition = Vector2.new(),
  1548.                     MainStartPosition = UDim2.new(),
  1549.                     MainStartSize = UDim2.new(),
  1550.                 };
  1551.  
  1552.                 local dBD = dragbtn.MouseButton1Down:Connect(function()
  1553.                     self.ResizeActive[frame].startPosition = Vector2.new(Mouse.X, Mouse.Y)
  1554.                     self.ResizeActive[frame].MainStartSize = main.Size;
  1555.                     self.ResizeActive[frame].MainStartPosition = main.Position;
  1556.                     self.ResizeActive[frame].Resizing = true;
  1557.                 end)
  1558.  
  1559.                 Cached_ResizeConnections[frame] = dBD;
  1560.             else
  1561.                 if Cached_ResizeConnections[frame] then
  1562.                     Cached_ResizeConnections[frame]:Disconnect();
  1563.                 end
  1564.                 self.ResizeActive[frame] = nil;
  1565.             end
  1566.         end,
  1567.     };
  1568.  
  1569.     metadata.__index = function(self, index)
  1570.         if methods[index] then
  1571.             return function(s, ...)
  1572.                 return methods[index](self, ...);
  1573.             end
  1574.         end
  1575.     end
  1576.  
  1577.     metadata.__call = function(self)
  1578.         FrostHook:RegisterConnection(FrostHook.Services.UserInputService.InputBegan, function(inputObject)
  1579.             local InputType = inputObject.UserInputType;
  1580.             if InputType == Enum.UserInputType.MouseButton1 then
  1581.                 for topbar,data in pairs(self.DragActive) do
  1582.                     if data.MouseOnTopBar then
  1583.                         data.Dragging = true;
  1584.                         data.startPosition = Vector2.new(Mouse.X, Mouse.Y)
  1585.                         data.TopbarPosition = topbar.Position;
  1586.                     end
  1587.                 end
  1588.             end
  1589.         end)
  1590.  
  1591.         FrostHook:RegisterConnection(FrostHook.Services.UserInputService.InputEnded, function(inputObject)
  1592.             local InputType = inputObject.UserInputType;
  1593.             if InputType == Enum.UserInputType.MouseButton1 then
  1594.                 for topbar,data in pairs(self.DragActive) do
  1595.                     data.Dragging = false;
  1596.                 end
  1597.                 for topbar,data in pairs(self.ResizeActive) do
  1598.                     data.Resizing = false;
  1599.                 end
  1600.             end
  1601.         end)
  1602.  
  1603.         local function KeepInBounds(_p, _s)
  1604.             local appropriated_p = _p
  1605.             local AbsolutePos = Vector2.new(((_p.X.Scale*Mouse.ViewSizeX)+_p.X.Offset), ((_p.Y.Scale*Mouse.ViewSizeY)+_p.Y.Offset))
  1606.            
  1607.             local S_O_X = _p.X.Scale * Mouse.ViewSizeX;
  1608.             local S_O_Y = _p.Y.Scale * Mouse.ViewSizeY;
  1609.            
  1610.             if AbsolutePos.X + _s.X >= Mouse.ViewSizeX then
  1611.                 appropriated_p = UDim2.new(
  1612.                     _p.X.Scale,
  1613.                     Mouse.ViewSizeX - S_O_X - _s.X,
  1614.                     appropriated_p.Y.Scale,
  1615.                     appropriated_p.Y.Offset
  1616.                 )
  1617.             end
  1618.            
  1619.             if AbsolutePos.X <= 0 then
  1620.                 appropriated_p = UDim2.new(
  1621.                     _p.X.Scale,
  1622.                     -S_O_X,
  1623.                     appropriated_p.Y.Scale,
  1624.                     appropriated_p.Y.Offset
  1625.                 )
  1626.             end
  1627.            
  1628.             if AbsolutePos.Y + _s.Y - 20 >= Mouse.ViewSizeY then
  1629.                 appropriated_p = UDim2.new(
  1630.                     appropriated_p.X.Scale,
  1631.                     appropriated_p.X.Offset,
  1632.                     _p.Y.Scale,
  1633.                     Mouse.ViewSizeY - S_O_Y - _s.Y + 20
  1634.                 )
  1635.             end
  1636.            
  1637.             if AbsolutePos.Y <= -20 then
  1638.                 appropriated_p = UDim2.new(
  1639.                     appropriated_p.X.Scale,
  1640.                     appropriated_p.X.Offset,
  1641.                     _p.Y.Scale,
  1642.                     -S_O_Y - 20
  1643.                 )
  1644.             end
  1645.            
  1646.             return appropriated_p;
  1647.         end
  1648.  
  1649.         local function ConstraintApply(_s)
  1650.             local appropriated_s = _s;
  1651.            
  1652.             if _s.X.Offset <= FrostHook.Constraints.Min.X.Offset then
  1653.                 appropriated_s = UDim2.new(0, FrostHook.Constraints.Min.X.Offset, 0, appropriated_s.Y.Offset)
  1654.             elseif _s.X.Offset >= FrostHook.Constraints.Max.X.Offset then
  1655.                 appropriated_s = UDim2.new(0, FrostHook.Constraints.Max.X.Offset, 0, appropriated_s.Y.Offset)
  1656.             end
  1657.            
  1658.             if _s.Y.Offset <= FrostHook.Constraints.Min.Y.Offset then -- Fix X Offset
  1659.                 appropriated_s = UDim2.new(0, appropriated_s.X.Offset, 0, FrostHook.Constraints.Min.Y.Offset)
  1660.             elseif _s.Y.Offset >= FrostHook.Constraints.Max.Y.Offset then
  1661.                 appropriated_s = UDim2.new(0, appropriated_s.X.Offset, 0, FrostHook.Constraints.Max.Y.Offset)
  1662.             end
  1663.            
  1664.             return appropriated_s;
  1665.         end
  1666.  
  1667.         FrostHook:RegisterConnection(FrostHook.Services.RunService.RenderStepped, function()
  1668.             for Topbar, Data in pairs(self.DragActive) do
  1669.                 local Main = Data.Main;
  1670.  
  1671.                 if Data.startPosition and Data.Dragging then
  1672.                     local AbsolutePixelChange = Vector2.new(Mouse.X,Mouse.Y) - Data.startPosition;
  1673.                     local AbsolutePixelUDim2 = UDim2.new(0,AbsolutePixelChange.X,0,AbsolutePixelChange.Y)
  1674.                     Topbar.Position = KeepInBounds(
  1675.                         (UDim2.new(
  1676.                             0.5, Data.TopbarPosition.X.Offset,
  1677.                             0.5, Data.TopbarPosition.Y.Offset)
  1678.                              + AbsolutePixelUDim2
  1679.                         ),
  1680.                         Main.AbsoluteSize
  1681.                     );
  1682.                 end
  1683.             end
  1684.  
  1685.             for Topbar, Data in pairs(self.ResizeActive) do
  1686.                 local Main = Data.Main;
  1687.  
  1688.                 if Data.startPosition and Data.Resizing then
  1689.                     local AbsolutePixelChange = Vector2.new(Mouse.X,Mouse.Y) - Data.startPosition;
  1690.                     local AbsolutePixelUDim2 = UDim2.new(0,AbsolutePixelChange.X,0,AbsolutePixelChange.Y)
  1691.                     Main.Size = ConstraintApply(Data.MainStartSize + AbsolutePixelUDim2)
  1692.                     Topbar.Size = UDim2.new(0,Main.Size.X.Offset,Topbar.Size.Y.Scale,Topbar.Size.Y.Offset)
  1693.                     Main.Position = Data.MainStartPosition;
  1694.                 end
  1695.             end
  1696.         end)
  1697.     end
  1698.  
  1699.     setmetatable(FrostHook.CustomDrag, metadata);
  1700. end
  1701.  
  1702. do -- Script Generation (WIP)
  1703.     local metadata = {}
  1704.     local methods = {
  1705.         var_name = function(self, Cache, value)
  1706.             local ttype = type(value)
  1707.             if ttype == "table" then
  1708.                 Cache["table"] = Cache["table"] + 1;
  1709.                 value = "table_"..tostring(Cache["table"])
  1710.             elseif ttype == "userdata" then
  1711.                 Cache["userdata"] = Cache["userdata"] + 1;    
  1712.                 value = "userdata_"..tostring(Cache["userdata"]);
  1713.             elseif ttype == "string" then
  1714.                 Cache["string"] = Cache["string"] + 1;
  1715.                 value = "string_"..tostring(Cache["string"]);
  1716.             elseif ttype == "number" then
  1717.                 Cache["number"] = Cache["number"] + 1;
  1718.                 value = "number_"..tostring(Cache["number"])
  1719.             elseif ttype == "boolean" then
  1720.                 Cache["boolean"] = Cache["boolean"] + 1;
  1721.                 value = "bool_"..tostring(Cache["boolean"])
  1722.             end
  1723.             return value, Cache
  1724.         end,
  1725.         transform_path = function(self, path) -- Pulled from Hydroxide @Modified
  1726.             local split = path:split('.')
  1727.             local result = ""
  1728.             local name = FrostHook.Services.Players.LocalPlayer.Name;
  1729.            
  1730.             if #split == 1 and not game:FindFirstChild(split[1]) then
  1731.                 return split[1] .. " --[[ Parent is \"nil\" or object is destroyed ]]"
  1732.             end
  1733.  
  1734.             if pcall(game.GetService, game, split[1]) then
  1735.                 split[1] = "GetService(\"" .. split[1] .. "\")"
  1736.             end
  1737.            
  1738.             for i,v in next, split do
  1739.                 if (v:sub(1, 1):match("%A") or v:find("%W")) and not v:find("GetService") then
  1740.                     result = result:sub(1, result:len())
  1741.                     v = "[\"" .. v .. "\"]"
  1742.                 elseif v:find("GetService") then
  1743.                     v = ':' .. v
  1744.                 else
  1745.                     v = '.' .. v
  1746.                 end
  1747.                
  1748.                 result = result .. v
  1749.             end
  1750.            
  1751.             result = result:gsub("GetService(\"Players\")." .. name, "GetService(\"Players\").LocalPlayer")
  1752.             result = result:gsub("GetService(\"Players\")[\"" .. name .. "\"]", "GetService(\"Players\").LocalPlayer")
  1753.  
  1754.             return "game" .. result
  1755.         end,
  1756.         transform_value = function(self, value) -- Pulled from Hydroxide @Modified
  1757.             local result = ""
  1758.             local ttype = typeof(value)
  1759.          
  1760.             if ttype == "table" then
  1761.                 result = result .. self:dump_table(value)
  1762.             elseif ttype == "string" then
  1763.                 result = result .. '"' .. value .. '"'
  1764.             elseif ttype == "Instance" then
  1765.                 result = result .. self:transform_path(value:GetFullName())
  1766.             elseif ttype == "Vector3" then
  1767.                 result = result .. "Vector3.new(" .. tostring(value) .. ")"
  1768.             elseif ttype == "CFrame" then
  1769.                 result = result .. "CFrame.new(" .. tostring(value) .. ")"
  1770.             elseif ttype == "Color3" then
  1771.                 result = result .. "Color3.new(" .. tostring(value) .. ")"
  1772.             elseif ttype == "Ray" then
  1773.                 local split = tostring(value):split('}, ')
  1774.                 local origin = split[1]:gsub('{', "Vector3.new("):gsub('}', ')')
  1775.                 local direction = split[2]:gsub('{', "Vector3.new("):gsub('}', ')')
  1776.                 result = result .. "Ray.new(" .. origin .. "), " .. direction .. ')'
  1777.             elseif ttype == "ColorSequence" then
  1778.                 result = result .. "ColorSequence.new(" .. self:dump_table(v.Keypoints) .. ')'
  1779.             elseif ttype == "ColorSequenceKeypoint" then
  1780.                 result = result .. "ColorSequenceKeypoint.new(" .. value.Time .. ", Color3.new(" .. tostring(value.Value) .. "))"
  1781.             else
  1782.                 if type(value) == "userdata" then
  1783.                     print(ttype)
  1784.                 end
  1785.                
  1786.                 result = result .. tostring(value)
  1787.             end
  1788.        
  1789.             return result
  1790.         end,
  1791.         dump_table = function(self, node, tree, indentation) -- Pulled from StackOverflow @ Alundaio // kris2k; @Modified
  1792.             local cache, stack, output = {},{},{}
  1793.             local depth = 1
  1794.  
  1795.             if type(node) ~= "table" then
  1796.                 return "only table type is supported, got " .. type(node)
  1797.             end
  1798.  
  1799.             if nil == indentation then indentation = 1 end
  1800.  
  1801.             local NEW_LINE = "\n"
  1802.             local TAB_CHAR = "\t"
  1803.  
  1804.             if nil == tree then
  1805.                 NEW_LINE = "\n"
  1806.             elseif not tree then
  1807.                 NEW_LINE = ""
  1808.                 TAB_CHAR = ""
  1809.             end
  1810.  
  1811.             local output_str = "{" .. NEW_LINE
  1812.  
  1813.             while true do
  1814.                 local size = 0
  1815.                 for k,v in pairs(node) do
  1816.                     size = size + 1
  1817.                 end
  1818.  
  1819.                 local cur_index = 1
  1820.                 for k,v in pairs(node) do
  1821.                     if (cache[node] == nil) or (cur_index >= cache[node]) then
  1822.                         if (string.find(output_str,"}",output_str:len())) then
  1823.                             output_str = output_str .. "," .. NEW_LINE
  1824.                         elseif not (string.find(output_str,NEW_LINE,output_str:len())) then
  1825.                             output_str = output_str .. NEW_LINE
  1826.                         end
  1827.                         table.insert(output,output_str)
  1828.                         output_str = ""
  1829.  
  1830.                         local key
  1831.                         if (type(k) == "number" or type(k) == "boolean") then
  1832.                             key = "["..tostring(k).."]"
  1833.                         else
  1834.                             key = '["'..tostring(k)..'"]'
  1835.                         end
  1836.                         if (type(v) == "number" or type(v) == "boolean") then
  1837.                             output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = "..tostring(v)
  1838.                         elseif (type(v) == "table") then
  1839.                             output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = {" .. NEW_LINE
  1840.                             table.insert(stack,node)
  1841.                             table.insert(stack,v)
  1842.                             cache[node] = cur_index+1
  1843.                             break
  1844.                         else
  1845.                             output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = '"..tostring(v).."'"
  1846.                         end
  1847.  
  1848.                         if (cur_index == size) then
  1849.                             output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
  1850.                         else
  1851.                             output_str = output_str .. ","
  1852.                         end
  1853.                     else
  1854.                         if (cur_index == size) then
  1855.                             output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
  1856.                         end
  1857.                     end
  1858.                     cur_index = cur_index + 1
  1859.                 end
  1860.  
  1861.                 if (size == 0) then
  1862.                     output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
  1863.                 end
  1864.  
  1865.                 if (#stack > 0) then
  1866.                     node = stack[#stack]
  1867.                     stack[#stack] = nil
  1868.                     depth = cache[node] == nil and depth + 1 or depth - 1
  1869.                 else
  1870.                     break
  1871.                 end
  1872.             end
  1873.             table.insert(output,output_str)
  1874.             return table.concat(output)
  1875.         end,
  1876.     }
  1877.  
  1878.     metadata.__index = function(self, index)
  1879.         if methods[index] then
  1880.             return function(s, ...)
  1881.                 return methods[index](self, ...);
  1882.             end
  1883.         end
  1884.     end
  1885.  
  1886.     setmetatable(FrostHook.ScriptGeneration, metadata);
  1887. end
  1888.  
  1889. do -- Text Editor
  1890.     local metadata = {};
  1891.     local methods = {
  1892.         CorrectTabs = function(self, code)
  1893.             return string.gsub(code, "\t", (string.rep("\t", self.TabSize+1)))
  1894.         end,
  1895.         RevertTabs = function(self, code)
  1896.             return code:gsub(string.rep("\t", self.TabSize+1), "\t")
  1897.         end,
  1898.         GetTextSize = function(self, text)
  1899.             text = (text~=nil)and text or "";
  1900.             return game:GetService("TextService"):GetTextSize(text, self.FontSize, self.Font, Vector2.new(math.huge, math.huge));
  1901.         end,
  1902.         SetCode = function(self, code)
  1903.             self.Imported = true;
  1904.             FrostHook.Interface.Topbar.Main.MainPanel.Code.Main.Input.Text = self:CorrectTabs(code);
  1905.         end,
  1906.         ExportCode = function(self, code)
  1907.             return self:RevertTabs(code);
  1908.         end,
  1909.         GetEndOfLine = function(self, code, start)
  1910.             local pos = start;
  1911.             while true do
  1912.                 local char = string.sub(code, pos, pos)
  1913.                 if string.byte(char) == 10 or string.byte(char) == 13 then
  1914.                     break;
  1915.                 elseif pos > string.len(code) then
  1916.                     break;
  1917.                 else
  1918.                     pos = pos + 1;
  1919.                 end
  1920.             end
  1921.             return pos - 1;
  1922.         end,
  1923.         GetStartOfLine = function(self, code, start)
  1924.             local pos = start;
  1925.             while true do
  1926.                 local char = string.sub(code, pos, pos)
  1927.                 if string.byte(char) == 10 or string.byte(char) == 13 then
  1928.                     break;
  1929.                 elseif pos <= 0 then
  1930.                     pos = 0;
  1931.                     break;
  1932.                 else
  1933.                     pos = pos - 1;
  1934.                 end
  1935.             end
  1936.             return pos + 1;
  1937.         end,
  1938.         GetLineText = function(self, code, start)
  1939.             local LineText = "";
  1940.             local first = self:GetStartOfLine(code, start);
  1941.             local second = self:GetEndOfLine(code, start);
  1942.             if first and second then
  1943.                 LineText = string.sub(code, first, second);
  1944.             end
  1945.             return LineText;
  1946.         end,
  1947.         ClearHighlights = function(self)
  1948.             for d,p in pairs(self.Cache) do
  1949.                 if p.Object then
  1950.                     p.Object:Destroy();
  1951.                 end
  1952.                 self.Cache[d] = nil;
  1953.             end
  1954.         end,
  1955.     };
  1956.    
  1957.     metadata.__index = function(self, index)
  1958.         if methods[index] then
  1959.             return function(s, ...)
  1960.                 return methods[index](self, ...);
  1961.             end
  1962.         end
  1963.     end
  1964.    
  1965.     metadata.__call = function(self)
  1966.         local Spy = FrostHook.Interface;
  1967.         local Templates = Spy.Templates;
  1968.         local Editor = Spy.Topbar.Main.MainPanel.Code;
  1969.         local Main = Editor.Main;
  1970.         local Highlights = Main.Highlights;
  1971.         local LineNumbers = Editor.Lines;
  1972.         local InputBox = Main.Input;
  1973.        
  1974.         FrostHook:RegisterConnection(InputBox:GetPropertyChangedSignal("Text"), function()
  1975.  
  1976.             local Lines = self:GetTextSize(InputBox.Text).Y/14
  1977.            
  1978.             if self.LineCache._len > Lines then
  1979.                 for i=Lines,self.LineCache._len,1 do
  1980.                     local Line = self.LineCache[i]
  1981.                     if Line then
  1982.                         Line:Destroy();
  1983.                         self.LineCache[i] = nil;
  1984.                     end
  1985.                 end
  1986.             end
  1987.            
  1988.             self.LineCache._len = Lines;
  1989.            
  1990.             for i=1,Lines do
  1991.                 local Line = self.LineCache[i]
  1992.                 if not Line then
  1993.                     Line = Templates.Line:Clone();
  1994.                     Line.Visible = true;
  1995.                     Line.Parent = LineNumbers;
  1996.                     self.LineCache[i] = Line;
  1997.                 end
  1998.                 Line.Text = i;
  1999.                 Line.Name = i;
  2000.                 Line.LayoutOrder = i;
  2001.             end
  2002.            
  2003.             Main.CanvasSize = UDim2.new(0,0,0,LineNumbers.Layout.AbsoluteContentSize.Y)
  2004.            
  2005.             if math.abs(InputBox.CursorPosition - string.len(InputBox.Text)) <= 5 then
  2006.                 Main.CanvasPosition = Vector2.new(0,LineNumbers.Layout.AbsoluteContentSize.Y)
  2007.             end
  2008.            
  2009.             self:ClearHighlights();
  2010.            
  2011.             if InputBox.Text ~= "" then
  2012.                 for keyword,data in pairs(FrostHook.Keywords) do
  2013.                     local lastPosition = 0;
  2014.                     local cachedPosition = -1;
  2015.                     local StackOverflow = false;
  2016.                     local patternA = data[2]
  2017.                     local patternB = data[3]
  2018.                     while true do
  2019.                         if lastPosition == cachedPosition then
  2020.                             warn("Highlighting had a stack overflow!")
  2021.                             break;
  2022.                         end
  2023.                         cachedPosition = lastPosition;
  2024.                         local a,b = string.find(InputBox.Text, patternA..keyword..patternB, lastPosition, false)
  2025.                         if a and b then
  2026.                             local word = string.sub(InputBox.Text, a, b)
  2027.                             local iterations = 0;
  2028.                             repeat
  2029.                                 iterations = iterations + 1;
  2030.                                 if iterations >= 5 then
  2031.                                     StackOverflow = true;
  2032.                                     break;
  2033.                                 end
  2034.                                 local first = word:sub(1,1);
  2035.                                 if first:find("%p") or first:find("%s") then
  2036.                                     a = a + 1;
  2037.                                     word = string.sub(InputBox.Text, a, b);
  2038.                                 end
  2039.                                 local last = word:sub(#word,#word)
  2040.                                 if last:find("%p") or last:find("%s") then
  2041.                                     b = b - 1;
  2042.                                     word = string.sub(InputBox.Text, a, b);
  2043.                                 end
  2044.                             until word == keyword or StackOverflow;
  2045.  
  2046.                             if not StackOverflow then
  2047.                                 local LineStart = self:GetStartOfLine(InputBox.Text, a);
  2048.                                 local LineText = InputBox.Text:sub(LineStart, a-1);
  2049.                                
  2050.                                 self.Cache[tostring(a..":"..b)] = {
  2051.                                     ["Word"] = word,
  2052.                                     ["LineText"] = LineText,
  2053.                                     ["Object"] = nil,
  2054.                                 }
  2055.                                 lastPosition = b;
  2056.                             else
  2057.                                 warn("Highlighting had a stack overflow!")
  2058.                             end;
  2059.                         else
  2060.                             break;
  2061.                         end
  2062.                     end
  2063.                 end
  2064.                
  2065.                 for PositionData,Data in pairs(self.Cache) do
  2066.                     if Data and Data.Word and Data.LineText then
  2067.                         local Word = Data.Word
  2068.                         local LineText = Data.LineText;
  2069.                         local KeywordData = FrostHook.Keywords[tostring(Word)]
  2070.                         if KeywordData then
  2071.                             local ColorData = KeywordData[1]
  2072.                             local a,b = unpack(string.split(PositionData, ":"));
  2073.                        
  2074.                             local LineHeight = InputBox.LineHeight;
  2075.                             local Relative_Y = self:GetTextSize(string.sub(InputBox.Text, 1, b)).Y
  2076.                             Relative_Y = Relative_Y * LineHeight - (LineHeight*3)
  2077.                             local Relative_X = self:GetTextSize(Data.LineText).X
  2078.                             local keywordSize = self:GetTextSize(Word)
  2079.                            
  2080.                             local newLabel = Templates.Highlight:Clone();
  2081.                                 newLabel.Position = UDim2.new(0,Relative_X,0,Relative_Y)
  2082.                                 newLabel.Size = UDim2.new(0,keywordSize.X,0,keywordSize.Y)
  2083.                                 newLabel.Text = Word;
  2084.                                 newLabel.Name = a..":"..b;
  2085.                                 newLabel.TextColor3 = ColorData;
  2086.                                 newLabel.TextStrokeColor3 = Color3.new(ColorData.r-0.4,ColorData.g-0.4,ColorData.b-0.4)
  2087.                             newLabel.Parent = Highlights;
  2088.                             self.Cache[PositionData].Object = newLabel;
  2089.                         end
  2090.                     end
  2091.                 end
  2092.             elseif Text == "" then
  2093.                 self.Imported = false;
  2094.             end
  2095.         end)
  2096.        
  2097.         FrostHook:RegisterConnection(FrostHook.Services.UserInputService.InputBegan, function(inputObject)
  2098.             local KeyCode = inputObject.KeyCode;
  2099.             local CursorPos = InputBox.CursorPosition
  2100.             local current_char = string.sub(InputBox.Text, CursorPos, CursorPos)
  2101.             local prev_char = string.sub(InputBox.Text, CursorPos-1,CursorPos-1)
  2102.             local next_char = string.sub(InputBox.Text, CursorPos+1,CursorPos+1)
  2103.            
  2104.             local CtrlDown = FrostHook.Services.UserInputService:IsKeyDown(Enum.KeyCode.LeftControl)
  2105.            
  2106.             if KeyCode == Enum.KeyCode.C and CtrlDown then
  2107.                 local Code = self.Imported and self:ExportCode(InputBox.Text) or InputBox.Text;
  2108.                 FrostHook.env.to_clipboard(Code);
  2109.             elseif KeyCode == Enum.KeyCode.V and CtrlDown then
  2110.                 self.Imported = false;
  2111.             elseif CtrlDown then
  2112.                 return;
  2113.             end
  2114.            
  2115.             if InputBox:IsFocused() and InputBox.Text ~= "" then
  2116.                 if KeyCode == Enum.KeyCode.Tab then -- working
  2117.                     local all_before = string.sub(InputBox.Text, 1, CursorPos-1);
  2118.                     local all_after = string.sub(InputBox.Text, CursorPos, string.len(InputBox.Text))
  2119.                     InputBox.Text = all_before..string.rep("\t", self.TabSize)..all_after;
  2120.                     InputBox.CursorPosition = CursorPos + self.TabSize;
  2121.                 elseif KeyCode == Enum.KeyCode.Backspace then
  2122.                     if prev_char == "\t" then
  2123.                         local all_before = string.sub(InputBox.Text, 1, CursorPos-self.TabSize-1);
  2124.                         local all_after = string.sub(InputBox.Text, CursorPos, string.len(InputBox.Text))
  2125.                         InputBox.Text = all_before..all_after;
  2126.                         InputBox.CursorPosition = CursorPos - self.TabSize;
  2127.                     end
  2128.                 elseif KeyCode == Enum.KeyCode.Left then
  2129.                     if current_char == "\t" then
  2130.                         CursorPos = CursorPos - self.TabSize;
  2131.                         InputBox.CursorPosition = CursorPos;
  2132.                     end
  2133.                 elseif KeyCode == Enum.KeyCode.Right then
  2134.                     if current_char == "\t" then
  2135.                         CursorPos = CursorPos + self.TabSize;
  2136.                         InputBox.CursorPosition = CursorPos;
  2137.                     end
  2138.                 elseif KeyCode == Enum.KeyCode.Up then
  2139.                     if current_char == "\n" then
  2140.                         CursorPos = CursorPos - 1;
  2141.                     end
  2142.                     local startLine = self:GetStartOfLine(InputBox.Text, CursorPos);
  2143.                     InputBox.CursorPosition = startLine - 1;
  2144.                 elseif KeyCode == Enum.KeyCode.Down then
  2145.                     local endLine = self:GetEndOfLine(InputBox.Text, CursorPos);
  2146.                     endLine = self:GetEndOfLine(InputBox.Text, endLine) + 2;
  2147.                     endLine = self:GetEndOfLine(InputBox.Text, endLine)
  2148.                     InputBox.CursorPosition = endLine + 1;
  2149.                 end
  2150.             end
  2151.         end)
  2152.     end
  2153.    
  2154.     setmetatable(FrostHook.TextEditor, metadata);
  2155. end
  2156.  
  2157. FrostHook(); -- Initialize FrostHook Spy.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement