local startupArgs = ({...})[1] or {} if getgenv().library ~= nil then getgenv().library:Unload(); end if not game:IsLoaded() then game.Loaded:Wait() end local function gs(a) return game:GetService(a) end -- // Variables local players, http, runservice, inputservice, tweenService, stats, actionservice = gs('Players'), gs('HttpService'), gs('RunService'), gs('UserInputService'), gs('TweenService'), gs('Stats'), gs('ContextActionService') local localplayer = players.LocalPlayer local setByConfig = false local floor, ceil, huge, pi, clamp = math.floor, math.ceil, math.huge, math.pi, math.clamp local c3new, fromrgb, fromhsv = Color3.new, Color3.fromRGB, Color3.fromHSV local next, newInstance, newUDim2, newVector2 = next, Instance.new, UDim2.new, Vector2.new local isexecutorclosure = isexecutorclosure or is_synapse_function or is_sirhurt_closure or iskrnlclosure; local executor = ( syn and 'syn' or getexecutorname and getexecutorname() or 'unknown' ) local library = { windows = {}; indicators = {}; flags = {}; options = {}; connections = {}; drawings = {}; instances = {}; utility = {}; notifications = {}; tweens = {}; theme = {}; zindexOrder = { ['indicator'] = 950; ['window'] = 1000; ['dropdown'] = 1200; ['colorpicker'] = 1100; ['watermark'] = 1300; ['notification'] = 1400; }, stats = { ['fps'] = 0; ['ping'] = 0; }; images = { ['gradientp90'] = 'https://raw.githubusercontent.com/portallol/luna/main/modules/gradient90.png'; ['gradientp45'] = 'https://raw.githubusercontent.com/portallol/luna/main/modules/gradient45.png'; ['colorhue'] = 'https://raw.githubusercontent.com/portallol/luna/main/modules/lgbtqshit.png'; ['colortrans'] = 'https://raw.githubusercontent.com/portallol/luna/main/modules/trans.png'; }; numberStrings = {['Zero'] = 0, ['One'] = 1, ['Two'] = 2, ['Three'] = 3, ['Four'] = 4, ['Five'] = 5, ['Six'] = 6, ['Seven'] = 7, ['Eight'] = 8, ['Nine'] = 9}; signal = loadstring(game:HttpGet('https://raw.githubusercontent.com/Quenty/NevermoreEngine/main/src/signal/src/Shared/Signal.lua'))(); open = false; opening = false; hasInit = false; cheatname = startupArgs.cheatname or 'octohook'; gamename = startupArgs.gamename or 'universal'; fileext = startupArgs.fileext or '.txt'; } library.themes = { { name = 'Default', theme = { ["Accent"] = fromrgb(204, 45, 45); ["Background"] = fromrgb(18,18,18); ["Border"] = fromrgb(0,0,0); ["Border 1"] = fromrgb(60,60,60); ["Border 2"] = fromrgb(18,18,18); ["Border 3"] = fromrgb(10,10,10); ["Primary Text"] = fromrgb(255,255,255); ["Group Background"] = fromrgb(18,18,18); ["Selected Tab Background"] = fromrgb(18,18,18); ["Unselected Tab Background"] = fromrgb(18,18,18); ["Selected Tab Text"] = fromrgb(245,245,245); ["Unselected Tab Text"] = fromrgb(145,145,145); ["Section Background"] = fromrgb(18,18,18); ["Option Text 1"] = fromrgb(255,255,255); ["Option Text 2"] = fromrgb(255,255,255); ["Option Text 3"] = fromrgb(255,255,255); ["Option Border 1"] = fromrgb(50,50,50); ["Option Border 2"] = fromrgb(0,0,0); ["Option Background"] = fromrgb(23,23,23); ["Risky Text"] = fromrgb(175, 21, 21); ["Risky Text Enabled"] = fromrgb(255, 41, 41); } }, { name = 'Informant_V1', theme = { ['Accent'] = fromrgb(103,89,179); ['Background'] = fromrgb(22,22,31); ['Border'] = fromrgb(0,0,0); ['Border 1'] = fromrgb(50,50,50); ['Border 2'] = fromrgb(24,25,37); ['Border 3'] = fromrgb(10,10,10); ['Primary Text'] = fromrgb(235,235,235); ['Group Background'] = fromrgb(24,25,37); ['Selected Tab Background'] = fromrgb(24,25,37); ['Unselected Tab Background'] = fromrgb(22,22,31); ['Selected Tab Text'] = fromrgb(245,245,245); ['Unselected Tab Text'] = fromrgb(145,145,145); ['Section Background'] = fromrgb(22,22,31); ['Option Text 1'] = fromrgb(245,245,245); ['Option Text 2'] = fromrgb(195,195,195); ['Option Text 3'] = fromrgb(145,145,145); ['Option Border 1'] = fromrgb(50,50,50); ['Option Border 2'] = fromrgb(0,0,0); ['Option Background'] = fromrgb(24,25,37); ["Risky Text"] = fromrgb(175, 21, 21); ["Risky Text Enabled"] = fromrgb(255, 41, 41); } }, { name = 'Fatality', theme = { ['Accent'] = fromrgb(197,7,83); ['Background'] = fromrgb(25,19,53); ['Border'] = fromrgb(0,0,0); ['Border 1'] = fromrgb(60,53,93); ['Border 2'] = fromrgb(29,23,66); ['Border 3'] = fromrgb(10,10,10); ['Primary Text'] = fromrgb(235,235,235); ['Group Background'] = fromrgb(29,23,66); ['Selected Tab Background'] = fromrgb(29,23,66); ['Unselected Tab Background'] = fromrgb(25,19,53); ['Selected Tab Text'] = fromrgb(245,245,245); ['Unselected Tab Text'] = fromrgb(145,145,145); ['Section Background'] = fromrgb(25,19,53); ['Option Text 1'] = fromrgb(245,245,245); ['Option Text 2'] = fromrgb(195,195,195); ['Option Text 3'] = fromrgb(145,145,145); ['Option Border 1'] = fromrgb(60,53,93); ['Option Border 2'] = fromrgb(0,0,0); ['Option Background'] = fromrgb(29,23,66); ["Risky Text"] = fromrgb(175, 21, 21); ["Risky Text Enabled"] = fromrgb(255, 41, 41); } }, { name = 'Gamesense', theme = { ['Accent'] = fromrgb(147,184,26); ['Background'] = fromrgb(17,17,17); ['Border'] = fromrgb(0,0,0); ['Border 1'] = fromrgb(47,47,47); ['Border 2'] = fromrgb(17,17,17); ['Border 3'] = fromrgb(10,10,10); ['Primary Text'] = fromrgb(235,235,235); ['Group Background'] = fromrgb(17,17,17); ['Selected Tab Background'] = fromrgb(17,17,17); ['Unselected Tab Background'] = fromrgb(17,17,17); ['Selected Tab Text'] = fromrgb(245,245,245); ['Unselected Tab Text'] = fromrgb(145,145,145); ['Section Background'] = fromrgb(17,17,17); ['Option Text 1'] = fromrgb(245,245,245); ['Option Text 2'] = fromrgb(195,195,195); ['Option Text 3'] = fromrgb(145,145,145); ['Option Border 1'] = fromrgb(47,47,47); ['Option Border 2'] = fromrgb(0,0,0); ['Option Background'] = fromrgb(35,35,35); ["Risky Text"] = fromrgb(175, 21, 21); ["Risky Text Enabled"] = fromrgb(255, 41, 41); } }, { name = 'Twitch', theme = { ['Accent'] = fromrgb(169,112,255); ['Background'] = fromrgb(14,14,14); ['Border'] = fromrgb(0,0,0); ['Border 1'] = fromrgb(45,45,45); ['Border 2'] = fromrgb(31,31,35); ['Border 3'] = fromrgb(10,10,10); ['Primary Text'] = fromrgb(235,235,235); ['Group Background'] = fromrgb(31,31,35); ['Selected Tab Background'] = fromrgb(31,31,35); ['Unselected Tab Background'] = fromrgb(17,17,17); ['Selected Tab Text'] = fromrgb(225,225,225); ['Unselected Tab Text'] = fromrgb(160,170,175); ['Section Background'] = fromrgb(17,17,17); ['Option Text 1'] = fromrgb(245,245,245); ['Option Text 2'] = fromrgb(195,195,195); ['Option Text 3'] = fromrgb(145,145,145); ['Option Border 1'] = fromrgb(45,45,45); ['Option Border 2'] = fromrgb(0,0,0); ['Option Background'] = fromrgb(24,24,27); ["Risky Text"] = fromrgb(175, 21, 21); ["Risky Text Enabled"] = fromrgb(255, 41, 41); } } } local blacklistedKeys = { Enum.KeyCode.Unknown, Enum.KeyCode.W, Enum.KeyCode.A, Enum.KeyCode.S, Enum.KeyCode.D, Enum.KeyCode.Slash, Enum.KeyCode.Tab, Enum.KeyCode.Escape } local whitelistedBoxKeys = { Enum.KeyCode.Zero, Enum.KeyCode.One, Enum.KeyCode.Two, Enum.KeyCode.Three, Enum.KeyCode.Four, Enum.KeyCode.Five, Enum.KeyCode.Six, Enum.KeyCode.Seven, Enum.KeyCode.Eight, Enum.KeyCode.Nine } local keyNames = { [Enum.KeyCode.LeftControl] = 'LCTRL'; [Enum.KeyCode.RightControl] = 'RCTRL'; [Enum.KeyCode.LeftShift] = 'LSHIFT'; [Enum.KeyCode.RightShift] = 'RSHIFT'; [Enum.UserInputType.MouseButton1] = 'MB1'; [Enum.UserInputType.MouseButton2] = 'MB2'; [Enum.UserInputType.MouseButton3] = 'MB3'; } library.button1down = library.signal.new() library.button1up = library.signal.new() library.mousemove = library.signal.new() library.unloaded = library.signal.new(); local button1down, button1up, mousemove = library.button1down, library.button1up, library.mousemove local mb1down = false; local utility = library.utility do function utility:Connection(signal, func) local c = signal:Connect(func) table.insert(library.connections, c) return c end function utility:Instance(class, properties) local inst = newInstance(class) for prop, val in next, properties or {} do local s,e = pcall(function() inst[prop] = val end) if not s then printconsole(e, 255,0,0) end end return inst end function utility:HasProperty(obj, prop) return ({(pcall(function() local a = obj[prop] end))})[1] end function utility:ToRGB(c3) return c3.R*255,c3.G*255,c3.B*255 end function utility:AddRGB(a,b) local r1,g1,b1 = self:ToRGB(a); local r2,g2,b2 = self:ToRGB(b); return fromrgb(clamp(r1+r2,0,255),clamp(g1+g2,0,255),clamp(b1+b2,0,255)) end function utility:ConvertNumberRange(val,oldmin,oldmax,newmin,newmax) return (((val - oldmin) * (newmax - newmin)) / (oldmax - oldmin)) + newmin end function utility:UDim2ToVector2(udim2, vector2) local x,y x = udim2.X.Offset + self:ConvertNumberRange(udim2.X.Scale,0,1,0,vector2.X) y = udim2.Y.Offset + self:ConvertNumberRange(udim2.Y.Scale,0,1,0,vector2.Y) return newVector2(x,y) end function utility:Lerp(a,b,c) return a + (b-a) * c end function utility:Tween(obj, prop, val, time, direction, style) if self:HasProperty(obj, prop) then if library.tweens[obj] then if library.tweens[obj][prop] then library.tweens[obj][prop]:Cancel() end end local startVal = obj[prop]; local a = 0; local tween = { Completed = library.signal.new(); }; library.tweens[obj] = library.tweens[obj] or {}; library.tweens[obj][prop] = tween; tween.Connection = self:Connection(runservice.RenderStepped, function(dt) a = a + (dt / time); if a >= 1 or obj == nil then tween:Cancel(); end pcall(function() local progress = tweenService:GetValue(a, style or Enum.EasingStyle.Linear, direction or Enum.EasingDirection.In) local newVal if typeof(startVal) == 'number' then newVal = utility:Lerp(startVal, val, progress); else newVal = startVal:Lerp(val, progress); end obj[prop] = newVal; end) end) function tween:Cancel() tween.Connection:Disconnect(); tween.Completed:Fire(); table.clear(tween); library.tweens[obj][prop] = nil; end return tween; else printconsole('unable to tween: invalid property '..tostring(prop)..' for object '..tostring(obj), 255,0,0) end end function utility:DetectTableChange(indexcallback,newindexcallback) if indexcallback == nil then warn('DetectTableChange: Argument #1 (indexcallback) is nil, function may not work as expected.') elseif newindexcallback == nil then warn('DetectTableChange: Argument #2 (newindexcallback) is nil, function may not work as expected.') end local proxy = newproxy(true); local mt = getmetatable(proxy); mt.__index = indexcallback mt.__newindex = newindexcallback return proxy end function utility:MouseOver(obj) local mousePos = inputservice:GetMouseLocation(); local x1 = obj.Position.X local y1 = obj.Position.Y local x2 = x1 + obj.Size.X local y2 = y1 + obj.Size.Y return (mousePos.X >= x1 and mousePos.Y >= y1 and mousePos.X <= x2 and mousePos.Y <= y2) end function utility:GetHoverObject() local objects = {} for i,v in next, library.drawings do if v.Object.Visible and v.Class == 'Square' and self:MouseOver(v.Object) then table.insert(objects,v.Object) end end table.sort(objects,function(a,b) return a.ZIndex > b.ZIndex end) return objects[1] end function utility:Draw(class, properties) local blacklistedProperties = {'Object','Children','Class'} local drawing = { Object = Drawing.new(class); Children = {}; ThemeColor = ''; OutlineThemeColor = ''; ThemeColorOffset = 0; OutlineThemeColorOffset = 0; Parent = nil; Size = newUDim2(0,0,0,0); Position = newUDim2(0,0,0,0); AbsoluteSize = newVector2(0,0); AbsolutePosition = newVector2(0,0); Hover = false; Visible = true; MouseButton1Down = library.signal.new(); MouseButton2Down = library.signal.new(); MouseButton1Up = library.signal.new(); MouseButton2Up = library.signal.new(); MouseEnter = library.signal.new(); MouseLeave = library.signal.new(); Class = class; } function drawing:Update() -- if drawing.Parent then local parent = drawing.Parent ~= nil and library.drawings[drawing.Parent.Object] or nil local parentSize,parentPos,parentVis = workspace.CurrentCamera.ViewportSize, Vector2.new(0,0), true; if parent ~= nil then parentSize = (parent.Class == 'Square' or parent.Class == 'Image') and parent.Object.Size or parent.Class == 'Text' and parent.TextBounds or workspace.CurrentCamera.ViewportSize parentPos = parent.Object.Position parentVis = parent.Object.Visible end if drawing.Class == 'Square' or drawing.Class == 'Image' then drawing.Object.Size = typeof(drawing.Size) == 'Vector2' and drawing.Size or typeof(drawing.Size) == 'UDim2' and utility:UDim2ToVector2(drawing.Size,parentSize) end if drawing.Class == 'Square' or drawing.Class == 'Image' or drawing.Class == 'Circle' or drawing.Class == 'Text' then drawing.Object.Position = parentPos + (typeof(drawing.Position) == 'Vector2' and drawing.Position or utility:UDim2ToVector2(drawing.Position,parentSize)) end drawing.Object.Visible = (parentVis and drawing.Visible) and true or false -- end drawing:UpdateChildren() end function drawing:UpdateChildren() for i,v in next, drawing.Children do v:Update() end end function drawing:GetDescendants() local descendants = {}; local function a(t) for _,v in next, t.Children do table.insert(descendants, v); a(v) end end a(self) return descendants; end library.drawings[drawing.Object] = drawing -- this is really stupid lol local proxy = utility:DetectTableChange( function(obj,i) return drawing[i] == nil and drawing.Object[i] or drawing[i] end, function(obj,i,v) if not table.find(blacklistedProperties,i) then local lastval = drawing[i] if i == 'Size' and (class == 'Square' or class == 'Image') then drawing.Object.Size = utility:UDim2ToVector2(v,drawing.Parent == nil and workspace.CurrentCamera.ViewportSize or drawing.Parent.Object.Size); drawing.AbsoluteSize = drawing.Object.Size; elseif i == 'Position' and (class == 'Square' or class == 'Image' or class == 'Text') then drawing.Object.Position = utility:UDim2ToVector2(v,drawing.Parent == nil and newVector2(0,0) or drawing.Parent.Object.Position); drawing.AbsolutePosition = drawing.Object.Position; elseif i == 'Parent' then if drawing.Parent ~= nil then drawing.Parent.Children[drawing] = nil end if v ~= nil then table.insert(v.Children,drawing) end elseif i == 'Visible' then drawing.Visible = v elseif i == 'Font' and v == 2 and executor == 'ScriptWare' then v = 1 end pcall(function() drawing.Object[i] = v end) if drawing[i] ~= nil or i == 'Parent' then drawing[i] = v end if table.find({'Size','Position','Position','Visible','Parent'},i) then drawing:Update() end if table.find({'ThemeColor','OutlineThemeColor','ThemeColorOffset','OutlineThemeColorOffset'},i) and lastval ~= v then library.UpdateThemeColors() end end end) function drawing:Remove() for i,v in next, self.Children do v:Remove(); end if drawing.Parent then drawing.Parent.Children[drawing.Object] = nil; end library.drawings[drawing.Object] = nil; drawing.Object:Remove(); table.clear(drawing); end properties = typeof(properties) == 'table' and properties or {} if class == 'Square' and properties.Filled == nil then properties.Filled = true; end if properties.Visible == nil then properties.Visible = true; end for i,v in next, properties do proxy[i] = v end drawing:Update() return proxy end end library.utility = utility function library:Unload() library.unloaded:Fire(); for _,c in next, self.connections do c:Disconnect() end for obj in next, self.drawings do obj:Remove() end table.clear(self.drawings) getgenv().library = nil end function library:init() if self.hasInit then return end local tooltipObjects = {}; makefolder(self.cheatname) makefolder(self.cheatname..'/assets') makefolder(self.cheatname..'/'..self.gamename) makefolder(self.cheatname..'/'..self.gamename..'/configs'); function self:SetTheme(theme) for i,v in next, theme do self.theme[i] = v; end self.UpdateThemeColors(); end function self:GetConfig(name) if isfile(self.cheatname..'/'..self.gamename..'/configs/'..name..self.fileext) then return readfile(self.cheatname..'/'..self.gamename..'/configs/'..name..self.fileext); end end function self:LoadConfig(name) local cfg = self:GetConfig(name) if not cfg then return end local s,e = pcall(function() setByConfig = true for flag,value in next, http:JSONDecode(cfg) do local option = library.options[flag] if option ~= nil then if option.class == 'toggle' then option:SetState(value == nil and false or (value == 1 and true or false)); elseif option.class == 'slider' then option:SetValue(value == nil and 0 or value) elseif option.class == 'bind' then option:SetBind(value == nil and 'none' or (utility:HasProperty(Enum.KeyCode, value) and Enum.KeyCode[value] or Enum.UserInputType[value])); elseif option.class == 'color' then option:SetColor(value == nil and c3new(1,1,1) or c3new(value[1], value[2], value[3])); option:SetTrans(value == nil and 1 or value[4]); elseif option.class == 'list' then option:Select(value == nil and '' or value); elseif option.class == 'box' then option:SetInput(value == nil and '' or value) end end end setByConfig = false end) end function self:SaveConfig(name) if not self:GetConfig(name) then return end local s,e = pcall(function() local cfg = {}; for flag,option in next, self.options do if option.class == 'toggle' then cfg[flag] = option.state and 1 or 0; elseif option.class == 'slider' then cfg[flag] = option.value; elseif option.class == 'bind' then cfg[flag] = option.bind.Name; elseif option.class == 'color' then cfg[flag] = { option.color.r, option.color.g, option.color.b, option.trans, } elseif option.class == 'list' then cfg[flag] = option.selected; elseif option.class == 'box' then cfg[flag] = option.input end end writefile(self.cheatname..'/'..self.gamename..'/configs/'..name..self.fileext, http:JSONEncode(cfg)); end) end for i,v in next, self.images do if not isfile(self.cheatname..'/assets/'..i..'.oh') then writefile(self.cheatname..'/assets/'..i..'.oh', game:HttpGet(v)) end self.images[i] = readfile(self.cheatname..'/assets/'..i..'.oh'); end local screenGui = Instance.new('ScreenGui'); screenGui.Parent = game:GetService('CoreGui'); screenGui.Enabled = true; utility:Instance('ImageButton', { Parent = screenGui, Visible = true, Modal = true, Size = UDim2.new(1,0,1,0), ZIndex = 9999999999, Transparency = 1; }) utility:Connection(library.unloaded, function() screenGui:Destroy() end) utility:Connection(inputservice.InputBegan, function(input, gpe) if self.hasInit then if input.KeyCode == self.toggleKey and not library.opening and not gpe then self:SetOpen(not self.open) task.spawn(function() library.opening = true; task.wait(.15); library.opening = false; end) end if library.open then local hoverObj = utility:GetHoverObject(); local hoverObjData = library.drawings[hoverObj]; if input.UserInputType == Enum.UserInputType.MouseButton1 then mb1down = true; button1down:Fire() if hoverObj and hoverObjData then hoverObjData.MouseButton1Down:Fire(inputservice:GetMouseLocation()) end -- // Update Sliders Click if library.draggingSlider ~= nil then local rel = inputservice:GetMouseLocation() - library.draggingSlider.objects.background.Object.Position; local val = utility:ConvertNumberRange(rel.X, 0 , library.draggingSlider.objects.background.Object.Size.X, library.draggingSlider.min, library.draggingSlider.max); library.draggingSlider:SetValue(val) end elseif input.UserInputType == Enum.UserInputType.MouseButton2 then if hoverObj and hoverObjData then hoverObjData.MouseButton2Down:Fire(inputservice:GetMouseLocation()) end end end end end) utility:Connection(inputservice.InputEnded, function(input, gpe) if self.hasInit and library.open then local hoverObj = utility:GetHoverObject(); local hoverObjData = library.drawings[hoverObj]; if input.UserInputType == Enum.UserInputType.MouseButton1 then mb1down = false; button1up:Fire(); if hoverObj and hoverObjData then hoverObjData.MouseButton1Up:Fire(inputservice:GetMouseLocation()) end elseif input.UserInputType == Enum.UserInputType.MouseButton2 then if hoverObj and hoverObjData then hoverObjData.MouseButton2Up:Fire(inputservice:GetMouseLocation()) end end end end) utility:Connection(inputservice.InputChanged, function(input, gpe) if input.UserInputType == Enum.UserInputType.MouseMovement then if library.open then mousemove:Fire(inputservice:GetMouseLocation()); if library.CurrentTooltip ~= nil then local mousePos = inputservice:GetMouseLocation() tooltipObjects.background.Position = UDim2.new(0,mousePos.X + 15,0,mousePos.Y + 15) tooltipObjects.background.Size = UDim2.new(0,tooltipObjects.text.TextBounds.X + 6 + (library.CurrentTooltip.risky and 60 or 0),0,tooltipObjects.text.TextBounds.Y + 2) end local hoverObj = utility:GetHoverObject(); for _,v in next, library.drawings do local hover = hoverObj == v.Object; if hover and not v.Hover then v.Hover = true; v.MouseEnter:Fire(inputservice:GetMouseLocation()); elseif not hover and v.Hover then v.Hover = false; v.MouseLeave:Fire(inputservice:GetMouseLocation()); end end if mb1down then -- // Update Sliders Drag if library.draggingSlider ~= nil then local rel = inputservice:GetMouseLocation() - library.draggingSlider.objects.background.Object.Position; local val = utility:ConvertNumberRange(rel.X, 0 , library.draggingSlider.objects.background.Object.Size.X, library.draggingSlider.min, library.draggingSlider.max); library.draggingSlider:SetValue(val) end end end end end) function self:SetOpen(bool) self.open = bool; screenGui.Enabled = bool; if bool and library.flags.disablemenumovement then actionservice:BindAction( 'FreezeMovement', function() return Enum.ContextActionResult.Sink end, false, unpack(Enum.PlayerActions:GetEnumItems()) ) else actionservice:UnbindAction('FreezeMovement'); end for _,window in next, self.windows do window:SetOpen(bool); end library.CurrentTooltip = nil; tooltipObjects.background.Visible = false end function self.UpdateThemeColors() for _,v in next, library.drawings do if v.ThemeColor and library.theme[v.ThemeColor] then v.Object.Color = utility:AddRGB(library.theme[v.ThemeColor],fromrgb(v.ThemeColorOffset,v.ThemeColorOffset,v.ThemeColorOffset)) end if v.ThemeColorOutline and library.theme[v.ThemeColorOutline] then v.Object.OutlineColor = utility:AddRGB(library.theme[v.ThemeColorOutline],fromrgb(v.OutlineThemeColorOffset,v.OutlineThemeColorOffset,v.OutlineThemeColorOffset)) end end end function self:SendNotification(message, time, color) time = time or 5 if typeof(message) ~= 'string' then return error(string.format('invalid message type, got %s, expected string', typeof(message))) elseif typeof(time) ~= 'number' then return error(string.format('invalid time type, got %s, expected number', typeof(time))) elseif color ~= nil and typeof(color) ~= 'Color3' then return error(string.format('invalid color type, got %s, expected color3', typeof(time))) end local notification = {}; self.notifications[notification] = true do local objs = notification; local z = self.zindexOrder.notification; notification.holder = utility:Draw('Square', { Position = newUDim2(0, 0, 0, 75); Transparency = 0; }) notification.background = utility:Draw('Square', { Size = newUDim2(1,0,1,0); Position = newUDim2(0, -500, 0, 0); Parent = notification.holder; ThemeColor = 'Background'; ZIndex = z; }) notification.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 2'; Parent = notification.background; ZIndex = z-1; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; Parent = objs.border1; ZIndex = z-2; }) notification.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = self.images.gradientp90; Parent = notification.background; Transparency = .5; ZIndex = z+1; }) notification.accentBar = utility:Draw('Square',{ Size = newUDim2(0,5,1,4); Position = newUDim2(0,0,0,-2); Parent = notification.background; ThemeColor = color == nil and 'Accent' or ''; ZIndex = z+5; }) notification.text = utility:Draw('Text', { Position = newUDim2(0,13,0,2); ThemeColor = 'Primary Text'; Text = message; Outline = true; Font = 2; Size = 13; ZIndex = z+4; Parent = notification.background; }) if color then notification.accentBar.Color = color; end end function notification:Remove() library.notifications[notification] = nil; self.holder:Remove(); library:UpdateNotifications() end task.spawn(function() self:UpdateNotifications(); notification.background.Size = newUDim2(0, notification.text.TextBounds.X + 20, 0, 19) task.wait(); utility:Tween(notification.background, 'Position', newUDim2(0,0,0, 0), .1); task.wait(time); for i,v in next, notification do if typeof(v) ~= 'function' then utility:Tween(v, 'Transparency', 0, .15); end end utility:Connection(utility:Tween(notification.background, 'Position', newUDim2(0,-500,0, 0), .25).Completed, (function() notification:Remove(); end)) end) end function self:UpdateNotifications() local i = 0 for v in next, self.notifications do utility:Tween(v.holder, 'Position', newUDim2(0,0,0, 75 + (i * 30)), .15) i += 1 end end function self.NewIndicator(data) local indicator = { title = data.title or 'indicator', enabled = data.enabled or false, position = data.position or newUDim2(0,15,0,300), values = {}, objects = {valueObjects = {}}, spacing = ' ', }; table.insert(self.indicators, indicator) -- Create Objects -- do local z = self.zindexOrder.indicator; local objs = indicator.objects; objs.background = utility:Draw('Square', { Size = newUDim2(0, 200, 0, 16); Position = indicator.position; ThemeColor = 'Background'; ZIndex = z; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 2'; Parent = objs.background; ZIndex = z-1; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; Parent = objs.border1; ZIndex = z-2; }) objs.topborder = utility:Draw('Square', { Size = newUDim2(1,0,0,1); ThemeColor = 'Accent'; Parent = objs.background; ZIndex = z+1; }) objs.textlabel = utility:Draw('Text', { Position = newUDim2(.5,0,0,1); ThemeColor = 'Primary Text'; Text = indicator.title; Size = 13; Font = 2; ZIndex = z+2; Center = true; Outline = true; Parent = objs.background; }); end -------------------- function indicator:Update() local xSize = 125 local yPos = 0 table.sort(self.values, function(a,b) return a.order < b.order; end) for _,v in next, self.values do v.objects.keyLabel.Text = tostring(v.key); v.objects.valueLabel.Text = tostring(v.value); v.objects.valueLabel.Position = newUDim2(1,-(v.objects.valueLabel.TextBounds.X + 3),0,0) v.objects.background.Position = newUDim2(0,0,1,3 + yPos) v.objects.background.Visible = v.enabled if v.enabled then yPos = yPos + 16 + 3 local x = (v.objects.keyLabel.TextBounds.X + 10 + v.objects.valueLabel.TextBounds.X) if x > xSize then xSize = x end end end self.objects.background.Size = newUDim2(0,xSize + 8,0,16) self.objects.background.Position = self.position end function indicator:AddValue(data) local value = { key = data.key or '', value = data.value or '', order = data.order or #self.values+1, enabled = data.enabled == nil and true or data.enabled, objects = {}, } table.insert(self.values, value); -- Create Objects -- do local z = library.zindexOrder.indicator; local objs = value.objects; objs.background = utility:Draw('Square', { Size = newUDim2(1, 0, 0, 16); ThemeColor = 'Background'; ZIndex = z; Parent = indicator.objects.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 2'; Parent = objs.background; ZIndex = z-1; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; Parent = objs.border1; ZIndex = z-2; }) objs.keyLabel = utility:Draw('Text', { Position = newUDim2(0,3,0,1); ThemeColor = 'Option Text 2'; Size = 13; Font = 2; ZIndex = z+2; Outline = true; Parent = objs.background; }); objs.valueLabel = utility:Draw('Text', { Position = newUDim2(0,0,0,1); ThemeColor = 'Option Text 2'; Size = 13; Font = 2; ZIndex = z+2; Outline = true; Parent = objs.background; }); end -------------------- function value:Remove() table.remove(indicator.values, table.find(indicator.values, value)) self.objects.background:Remove() table.clear(self) indicator:Update(); end function value:SetEnabled(bool) if typeof(bool) == 'boolean' then self.enabled = bool indicator:Update() end end function value:SetValue(str) if typeof(str) == 'string' then self.value = str indicator:Update() end end function value:SetKey(str) if typeof(str) == 'string' then self.key = str indicator:Update() end end self:Update() return value end function indicator:GetValue(idx) if typeof(idx) == 'number' then return self.values[idx] else for i,v in next, self.values do if v.key == idx then return v end end end end function indicator:SetEnabled(bool) if typeof(bool) == 'boolean' then self.enabled = bool; self.objects.background.Visible = bool; self:Update(); end end function indicator:SetPosition(udim2) if typeof(udim2) == 'UDim2' then self.position = udim2 self.objects.background.Position = udim2; end end for i,v in next, data.values or {} do indicator:AddValue({key = tostring(i), value = tostring(v)}) end indicator:SetEnabled(indicator.enabled); return indicator end function self.NewWindow(data) local window = { title = data.title or '', selectedTab = nil; tabs = {}, objects = {}, colorpicker = { objects = {}; color = c3new(1,0,0); trans = 0; }; dropdown = { objects = { values = {}; }; max = 5; } }; table.insert(library.windows, window); ----- Create Objects ---- do local size = data.size or newUDim2(0, 525, 0, 650); local position = data.position or newUDim2(0, 250, 0, 150); local objs = window.objects; local z = library.zindexOrder.window; objs.background = utility:Draw('Square', { Size = size; Position = position; ThemeColor = 'Background'; ZIndex = z; }) objs.innerBorder1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; ZIndex = z-1; Parent = objs.background; }) objs.innerBorder2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 1'; ZIndex = z-2; Parent = objs.innerBorder1; }) objs.midBorder = utility:Draw('Square', { Size = newUDim2(1,10,1,25); Position = newUDim2(0,-5,0,-20); ThemeColor = 'Border 2'; ZIndex = z-3; Parent = objs.innerBorder2; }) objs.outerBorder1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 1'; ZIndex = z-4; Parent = objs.midBorder; }) objs.outerBorder2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; ZIndex = z-5; Parent = objs.outerBorder1; }) objs.topBorder = utility:Draw('Square', { Size = newUDim2(1,0,0,1); ThemeColor = 'Accent'; ZIndex = z+1; Parent = objs.background; }) objs.title = utility:Draw('Text', { Position = newUDim2(0,7,0,2); ThemeColor = 'Primary Text'; Text = window.title; Font = 2; Size = 13; ZIndex = z+1; Outline = true; Parent = objs.midBorder; }) objs.groupBackground = utility:Draw('Square', { Size = newUDim2(1,-16,1,-(16+23)); Position = newUDim2(0,8,0,8+23); ThemeColor = 'Group Background'; ZIndex = z+5; Parent = objs.background; }) objs.groupInnerBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 1'; ZIndex = z+4; Parent = objs.groupBackground; }) objs.groupOuterBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; ZIndex = z+3; Parent = objs.groupInnerBorder; }) objs.tabHolder = utility:Draw('Square', { Size = newUDim2(1,0,0,20); Position = newUDim2(0,0,0,-21); Parent = objs.groupBackground; Transparency = 0; ZIndex = z+1; }) objs.columnholder1 = utility:Draw('Square', { Size = newUDim2(.48, 0, .96, 0); Position = newUDim2(.01, 0, .02, 0); Transparency = 0; ZIndex = z+6; Parent = objs.groupBackground; }) objs.columnholder2 = utility:Draw('Square', { Size = newUDim2(.48, 0, .96, 0); Position = newUDim2(1 - (.48 + .01), 0, .02, 0); Transparency = 0; ZIndex = z+6; Parent = objs.groupBackground; }) objs.dragdetector = utility:Draw('Square',{ Size = newUDim2(1,0,1,0); Parent = objs.midBorder; Transparency = 0; ZIndex = z+2; }) local dragging, mouseStart, objStart; utility:Connection(objs.dragdetector.MouseButton1Down, function(pos) dragging = true; mouseStart = newUDim2(0, pos.X, 0, pos.Y); objStart = objs.background.Position; end) utility:Connection(button1up, function() dragging = false; end) utility:Connection(mousemove, function(pos) if dragging then if window.open then objs.background.Position = objStart + newUDim2(0, pos.X, 0, pos.Y) - mouseStart; else dragging = false end end end) end ------------------------- -- Create Color Picker -- do -- Objects do local objs = window.colorpicker.objects; local z = library.zindexOrder.colorpicker; objs.background = utility:Draw('Square', { Visible = false; Size = newUDim2(0,200,0,242); Position = newUDim2(1,-200,1,10); ThemeColor = 'Background'; ZIndex = z; Parent = window.objects.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border'; ZIndex = z-1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 1'; ZIndex = z-2; Parent = objs.border1; }) objs.border3 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border'; ZIndex = z-3; Parent = objs.border2; }) objs.statusText = utility:Draw('Text', { Position = newUDim2(0,5,0,4); Text = 'colorpicker_status_text'; ThemeColor = 'Option Text 1'; Size = 13; Font = 2; Outline = true; ZIndex = z+1; Parent = objs.background; }) objs.mainColor = utility:Draw('Square', { Size = newUDim2(0, 175, 0, 175); Position = newUDim2(0, 5, 0, 25); Color = c3new(1,0,0); ZIndex = z+2; Parent = objs.background; }) objs.sat1 = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = base64_decode"iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAQAAADURZm+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQflBwwSLzK3wl3KAAADrElEQVR42u3TORLCMBBFwT+6/50hMqXSZgonBN0BWCDGYPwqeSWVZPWYVHd0Pc5H86v9areu4Sz9u7XZXT/vvtZtu6dtJtYw525iGya05afnWW17ltPE8fzfTZy/yf3vmCes59xf0Sf/42l3lnvGOyyH+y/bo/X689wCPCYkEBIICYQECAmEBEICIQFCAiGBkEBIgJBASCAkEBIgJBASCAmEBAgJhARCAiEBQgIhgZAAIYGQQEggJEBIICQQEggJEBIICYQEQgKEBEICIYGQACGBkEBIICRASCAkEBIICRASCAmEBAgJhARCAiEBQgIhgZBASICQQEggJBASICQQEggJhAQICYQEQgIhAUICIYGQQEguAQgJhARCAoQEQgIhgZAAIYGQQEggJEBIICQQEggJEBIICYQEQgKEBEICIYGQACGBkEBIgJBASCAkEBIgJBASCAmEBAgJhARCAiEBQgIhgZBASICQQEggJBASICQQEggJhAQICYQEQgKEBEICIYGQACGBkEBIICRASCAkEBIICRASCAmEBEIChARCAiGBkAAhgZBASCAkQEggJBASICQQEggJhAQICYQEQgIhAUICIYGQQEiAkEBIICQQEiAkEBIICYQECAmEBEIChARCAiGBkAAhgZBASCAkQEggJBASCAkQEggJhARCAoQEQgIhgZAAIYGQQEggJEBIICQQEiAkEBIICYQECAmEBEICIQFCAiGBkEBIgJBASCAkEBIgJBASCAmEBAgJhARCAiEBQgIhgZAAIYGQQEggJEBIICQQEggJEBIICYQEQgKEBEICIYGQACGBkEBIICRASCAkEBIgJBASCAmEBAgJhARCAiEBQgIhgZBASICQQEggJBASICQQEggJhAQICYQEQgIhAUICIYGQACGBkEBIICRASCAkEBIICRASCAmEBEIChARCAiGBkAAhgZBASCAkQEggJBASCAkQEggJhAQICYQEQgIhAUICIYGQQEiAkEBIICQQEiAkEBIICYQECAmEBEICIQFCAiGBkEBILgEICYQEQgKEBEICIYGQACGBkEBIICRASCAkEBIICRASCAmEBEIChARCAiGBkAAhgZBASICQQEggJBASICQQEggJhAQICYQEQgIhAUICIYGQQEiAkEBIICQQEiAkEBIICYQECAmEBEIChARCAiGBkAAhgZBASCAkQEggJBASCAkQEggJhARCAoQEQgIhgZAAIYGQQEggJEBIICQQEiAkEBL8lzft9AVFFzN+ywAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wNy0xMlQxODo0Nzo1MCswMDowMIxlM90AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDctMTJUMTg6NDc6NTArMDA6MDD9OIthAAAAAElFTkSuQmCC"; ZIndex = z+3; Parent = objs.mainColor; }) objs.sat2 = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = base64_decode"iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkCAQAAADURZm+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQflBwwSLyBEeyyCAAAD4klEQVR42u3YwQnAQAhFQTek/5pz9eBtEYzMlBD4PDcRADDBieMjwK3HJwBDghFepx0oEhgSOO0ARQJDAqcdKBJgSGBI4I0EhgQ47cCQwJDAGwlQJDAkcNqBIgGKBIoEhgROO0CRQJFAkQBDAqcdGBI47QBFAkUCQwKnHaBIoEigSKBIgCKBIYHTDhQJUCQwJHDagSIBigSGBE47UCRAkcCQwGkHKBIoEigSGBLgtANDAkMCbyTAkMBpB4oEigQoEhgSOO1AkQBDAqcdKBIoEqBIYEjgtANFUiRQJFAkMCTAaQeKBIoEigQYEjjtQJFAkQBFAkMCpx0oEmBI4LQDRQJFAhQJDAmcdqBIgCKBIoEhAU47UCRQJFAkwJDAaQeKBIYEOO1AkUCRYHuRTAmcduC0A0UCFAkUCQwJnHaAIoEigSKBIQFOO2gvkimBIoE3EhgS4LQDRQJDAqcdoEigSKBIYEiAIYEhwXx+NoAigSGB0w5QJDAkMCQwJKDiZwMoEhgSOO0ARQJFgnlFMiVw2oHTDhQJUCRQJDAkcNoBVZFMCRQJvJHAkACnHSgSKBIoElANSZPAaQdOOzAkwGkHigSGBIYEGBK08LMBFAkUCRQJMCQwJDAkWMjPBlAkMCRw2gG5SKYEigTeSGBIgNMOFAkMCQwJMCRo4WcDKBIYEjjtgFwkUwJFAm8kMCTAaQeKBIoEigRUQ9IkcNqB0w4MCXDagSKBIsHCIpkSOO3AaQeKBCgSKBIYEhgSYEjQws8GUCQwJHDaAblIpgSKBN5IYEiA0w4UCQwJDAkwJGjhZwMoEhgSOO0ARQJDAkMCQwIqfjaAIoEigSIBhgROO5hXJFMCpx047UCRAEUCRQJDAqcdUBXJlECRwBsJDAlw2oEigSKBIgGGBIYEhgSL+dkAigSGBE47QJHAkMBpB4oEGBIYEhgSrOZnAygSKBIoEmBI4LQDRQJFAhQJDAmcdrC8SKYEigTeSGBIgNMOFAkMCZx2gCKBIoEigSEBTjtQJFAkUCTAkMBpB4oEigQoEhgSOO1AkQBDAqcdKBKgSKBIYEjgtAMUCRQJFAkMCXDagSKBIoEiAYYETjtQJFAkQJHAkMBpB4oEGBI47UCRQJEARQJDAqcdoEigSGBI4LQDFAkUCRQJFAkwJHDagSKBIQFOOzAkMCTwRgIMCZx2oEigSIAigSKBIYHTzkcARQJFAkMCnHZgSGBI4I0EGBI47UCRQJEAQwKnHSgSKBKgSGBI4LQDRQIUCRQJDAmcdoAigSGB0w5QJFAkUCQwJMBpB4oEhgROO0CRwJDAkMAbCVAkMCT4gw/reQYigE05fAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wNy0xMlQxODo0NzozMiswMDowMN2VK3MAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDctMTJUMTg6NDc6MzIrMDA6MDCsyJPPAAAAAElFTkSuQmCC"; ZIndex = z+4; Parent = objs.mainColor; }) objs.colorBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border'; ZIndex = z+1; Parent = objs.mainColor; }) objs.mainDetector = utility:Draw('Square',{ Size = newUDim2(1,0,1,0); Transparency = 0; ZIndex = z+10; Parent = objs.mainColor; }) objs.hue = utility:Draw('Image', { Size = newUDim2(0,175,0,10); Position = newUDim2(0,5,0,205); Data = library.images.colorhue; ZIndex = z+2; Parent = objs.background; }) objs.hueBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border'; ZIndex = z+1; Parent = objs.hue; }) objs.hueDetector = utility:Draw('Square',{ Size = newUDim2(1,0,1,0); Transparency = 0; ZIndex = z+10; Parent = objs.hue; }) objs.transColor = utility:Draw('Square', { Size = newUDim2(0,10,0,175); Position = newUDim2(0,185,0,25); Color = c3new(1,0,0); ZIndex = z+2; Parent = objs.background; }) objs.trans = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.colortrans; ZIndex = z+3; Parent = objs.transColor; }) objs.transBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border'; ZIndex = z+1; Parent = objs.transColor; }) objs.transDetector = utility:Draw('Square',{ Size = newUDim2(1,0,1,0); Transparency = 0; ZIndex = z+10; Parent = objs.transColor; }) objs.pointer = utility:Draw('Square', { Size = newUDim2(0,2,0,2); Position = newUDim2(0,0,0,0); Color = c3new(1,1,1); ZIndex = z+6; Parent = objs.mainColor; }) objs.pointerBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); Color = c3new(0,0,0); ZIndex = z+5; Parent = objs.pointer; }) objs.hueSlider = utility:Draw('Square', { Size = newUDim2(0,1,1,0); Color = c3new(1,1,1); ZIndex = z+4; Parent = objs.hue; }) objs.hueSliderBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); Color = c3new(0,0,0); ZIndex = z+3; Parent = objs.hueSlider; }) objs.transSlider = utility:Draw('Square', { Size = newUDim2(1,0,0,1); Color = c3new(1,1,1); ZIndex = z+5; Parent = objs.trans; }) objs.transSliderBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); Color = c3new(0,0,0); ZIndex = z+4; Parent = objs.transSlider; }) objs.rBackground = utility:Draw('Square', { Size = newUDim2(0, 60, 0, 15); Position = newUDim2(0, 5, 1, - 20); ThemeColor = 'Option Background'; Parent = objs.background; ZIndex = z+5; }) objs.rBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); Color = c3new(0,0,0); ZIndex = z+4; Parent = objs.rBackground; }) objs.rText = utility:Draw('Text', { Position = newUDim2(.5,0,0,0); Color = c3new(1,.1,.1); Text = 'R'; Size = 13; Font = 2; Outline = true; Center = true; ZIndex = z+6; Parent = objs.rBackground; }) objs.gBackground = utility:Draw('Square', { Size = newUDim2(0, 60, 0, 15); Position = newUDim2(0, 70, 1, - 20); ThemeColor = 'Option Background'; Parent = objs.background; ZIndex = z+5; }) objs.gBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); Color = c3new(0,0,0); ZIndex = z+4; Parent = objs.gBackground; }) objs.gText = utility:Draw('Text', { Position = newUDim2(.5,0,0,0); Color = c3new(.1,1,.1); Text = 'G'; Size = 13; Font = 2; Outline = true; Center = true; ZIndex = z+6; Parent = objs.gBackground; }) objs.bBackground = utility:Draw('Square', { Size = newUDim2(0, 60, 0, 15); Position = newUDim2(0, 135, 1, - 20); ThemeColor = 'Option Background'; Parent = objs.background; ZIndex = z+5; }) objs.bBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); Color = c3new(0,0,0); ZIndex = z+4; Parent = objs.bBackground; }) objs.bText = utility:Draw('Text', { Position = newUDim2(.5,0,0,0); Color = c3new(.1,.1,1); Text = 'B'; Size = 13; Font = 2; Outline = true; Center = true; ZIndex = z+6; Parent = objs.bBackground; }) local draggingHue, draggingSat, draggingTrans = false, false, false; local function updateSatVal(pos) if window.colorpicker.selected ~= nil then local hue, sat, val = window.colorpicker.selected.color:ToHSV() X = (objs.mainColor.Object.Position.X + objs.mainColor.Object.Size.X) - objs.mainColor.Object.Position.X Y = (objs.mainColor.Object.Position.Y + objs.mainColor.Object.Size.Y) - objs.mainColor.Object.Position.Y X = math.clamp((pos.X - objs.mainColor.Object.Position.X) / X, 0, 0.995) Y = math.clamp((pos.Y - objs.mainColor.Object.Position.Y) / Y, 0, 0.995) sat, val = 1 - X, 1 - Y; window.colorpicker.selected:SetColor(fromhsv(hue,sat,val)); window.colorpicker:Visualize(fromhsv(hue, sat, val), window.colorpicker.selected.trans); end end local function updateHue(pos) if window.colorpicker.selected ~= nil then local hue, sat, val = window.colorpicker.selected.color:ToHSV() X = (objs.hue.Object.Position.X + objs.hue.Object.Size.X) - objs.hue.Object.Position.X X = math.clamp((pos.X - objs.hue.Object.Position.X) / X, 0, 0.995) hue = 1 - X window.colorpicker.selected:SetColor(fromhsv(hue,sat,val)); window.colorpicker:Visualize(fromhsv(hue, sat, val), window.colorpicker.selected.trans); end end local function updateTrans(pos) if window.colorpicker.selected ~= nil then Y = (objs.trans.Object.Position.Y + objs.trans.Object.Size.Y) - objs.trans.Object.Position.Y Y = math.clamp((pos.Y - objs.transColor.Object.Position.Y) / Y, 0, 0.995) window.colorpicker.selected:SetTrans(Y); window.colorpicker:Visualize(window.colorpicker.selected.color, Y); end end utility:Connection(objs.mainDetector.MouseButton1Down, function(pos) draggingSat = true; updateSatVal(pos) end) utility:Connection(objs.hueDetector.MouseButton1Down, function(pos) draggingHue = true; updateHue(pos) end) utility:Connection(objs.transDetector.MouseButton1Down, function(pos) draggingTrans = true; updateTrans(pos) end) utility:Connection(mousemove, function(pos) if library.open then if draggingSat then updateSatVal(pos) elseif draggingHue then updateHue(pos) elseif draggingTrans then updateTrans(pos) end end end) utility:Connection(button1up, function() draggingSat = false; draggingHue = false; draggingTrans = false; end) end function window.colorpicker:Visualize(c3, a) if typeof(c3) ~= 'Color3' then return end if typeof(a) ~= 'number' then return end local h,s,v = c3:ToHSV(); h = h == 0 and 1 or h; self.color = c3; self.trans = a; self.objects.mainColor.Color = fromhsv(h,1,1); self.objects.transColor.Color = fromhsv(h,s,v); self.objects.hueSlider.Position = newUDim2(1 - h, 0,0,0); self.objects.transSlider.Position = newUDim2(0,0,a,0); self.objects.pointer.Position = newUDim2(1 - s, 0, 1 - v, 0); self.objects.statusText.Text = 'Editing : Unknown'; if self.selected ~= nil then local txt = 'Editing : Unknown'; if self.selected.text ~= nil and self.selected.text ~= '' then txt = tostring(self.selected.text) elseif self.selected.flag ~= nil and self.selected.flag ~= '' then txt = tostring(self.selected.flag) end self.objects.statusText.Text = tostring(txt); end end window.colorpicker:Visualize(window.colorpicker.color, window.colorpicker.trans) end ------------------------- ---- Create Dropdown ---- do -- Default Objects do local objs = window.dropdown.objects; local z = library.zindexOrder.dropdown; objs.background = utility:Draw('Square', { Visible = false; Size = newUDim2(1,-3,0,50); Position = newUDim2(0,3,1,0); ThemeColor = 'Background'; ZIndex = z; Parent = window.objects.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border'; ZIndex = z-1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 1'; ZIndex = z-2; Parent = objs.border1; }) objs.border3 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border'; ZIndex = z-3; Parent = objs.border2; }) end function window.dropdown:Refresh() if self.selected ~= nil then local list = self.selected for idx, value in next, list.values do local valueObject = self.objects.values[idx] if valueObject == nil then valueObject = {}; valueObject.background = utility:Draw('Square', { Size = newUDim2(1,-4,0,18); Color = Color3.new(.25,.25,.25); Transparency = 0; ZIndex = library.zindexOrder.dropdown+1; Parent = self.objects.background; }) valueObject.text = utility:Draw('Text', { Position = newUDim2(0,3,0,1); ThemeColor = 'Option Text 2'; Text = tostring(value); Size = 13; Font = 2; ZIndex = library.zindexOrder.dropdown+2; Parent = valueObject.background; }) valueObject.connection = utility:Connection(valueObject.background.MouseButton1Down, function() local currentList = self.selected if currentList then local val = currentList.values[idx] local currentSelected = currentList.selected; local newSelected = currentList.multi and {} or val; if currentList.multi then for i,v in next, currentSelected do if v == "none" then continue end newSelected[i] = v; end if table.find(newSelected, val) then table.remove(newSelected, table.find(newSelected, val)); else table.insert(newSelected, val) end end currentList:Select(newSelected); if not currentList.multi then currentList.open = false; currentList.objects.openText.Text = '+'; window.dropdown.selected = nil; window.dropdown.objects.background.Visible = false; end for idx, val in next, currentList.values do local valueObj = self.objects.values[idx] if valueObj then valueObj.background.Transparency = (typeof(newSelected) == 'table' and table.find(newSelected, val) or newSelected == val) and 1 or 0 end end end end) self.objects.values[idx] = valueObject end end for idx, val in next, list.values do local valueObj = self.objects.values[idx] if valueObj then valueObj.background.Transparency = (typeof(list.selected) == 'table' and table.find(list.selected, val) or list.selected == val) and 1 or 0 end end local y,padding = 2,2 for idx, obj in next, self.objects.values do local valueStr = list.values[idx] obj.background.Visible = valueStr ~= nil if valueStr ~= nil then obj.background.Position = newUDim2(0,2,0,y); obj.text.Text = valueStr; y = y + obj.background.Object.Size.Y + padding; end end self.objects.background.Size = newUDim2(1,-6,0,y); end end window.dropdown:Refresh(); end ------------------------- local function tooltip(option) utility:Connection(option.objects.holder.MouseEnter, function() tooltipObjects.background.Visible = (not (option.tooltip == '' or option.tooltip == nil)) and true or false; tooltipObjects.riskytext.Visible = option.risky; tooltipObjects.text.Position = option.risky and newUDim2(0,60,0,0) or newUDim2(0,3,0,0) tooltipObjects.text.Text = tostring(option.tooltip); library.CurrentTooltip = option; end) utility:Connection(option.objects.holder.MouseLeave, function() if library.CurrentTooltip == option then library.CurrentTooltip = nil; tooltipObjects.background.Visible = false end end) end local visValues = {}; function window:SetOpen(bool) if typeof(bool) == 'boolean' then self.open = bool; local objs = self.objects.background:GetDescendants() table.insert(objs, self.objects.background) task.spawn(function() if not bool then task.wait(.1); end self.objects.background.Visible = bool; end) for _,v in next, objs do if v.Object.Transparency ~= 0 then task.spawn(function() if bool then utility:Tween(v.Object, 'Transparency', visValues[v] or 1, .1); else visValues[v] = v.Object.Transparency; utility:Tween(v.Object, 'Transparency', .05, .1); end end) end end end end function window:AddTab(text, order) local tab = { text = text; order = order or #self.tabs+1; callback = function() end; objects = {}; sections = {}; } table.insert(self.tabs, tab); --- Create Objects --- do local objs = tab.objects; local z = library.zindexOrder.window + 5; objs.background = utility:Draw('Square', { Size = newUDim2(0,50,1,0); Parent = self.objects.tabHolder; ThemeColor = 'Unselected Tab Background'; ZIndex = z; }) objs.innerBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 1'; ZIndex = z-1; Parent = objs.background; }) objs.outerBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; ZIndex = z-2; Parent = objs.innerBorder; }) objs.topBorder = utility:Draw('Square', { Size = newUDim2(1,0,0,1); ThemeColor = 'Unselected Tab Background'; ZIndex = z+1; Parent = objs.background; }) objs.text = utility:Draw('Text', { ThemeColor = 'Unselected Tab Text'; Text = text; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Center = true; Parent = objs.background; }) utility:Connection(objs.background.MouseButton1Down, function() tab:Select(); end) end ---------------------- function tab:AddSection(text, side, order) local section = { text = tostring(text); side = side == nil and 1 or clamp(side,1,2); order = order or #self.sections+1; enabled = true; objects = {}; options = {}; }; table.insert(self.sections, section); --- Create Objects --- do local objs = section.objects; local z = library.zindexOrder.window+15; objs.background = utility:Draw('Square', { ThemeColor = 'Section Background'; ZIndex = z; Parent = window.objects['columnholder'..(section.side)]; }) objs.innerBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,1); Position = newUDim2(0,-1,0,0); ThemeColor = 'Border 3'; ZIndex = z-1; Parent = objs.background; }) objs.outerBorder = utility:Draw('Square', { Size = newUDim2(1,2,1,1); Position = newUDim2(0,-1,0,0); ThemeColor = 'Border 1'; ZIndex = z-2; Parent = objs.innerBorder; }) objs.topBorder1 = utility:Draw('Square', { Size = newUDim2(.025,1,0,1); Position = newUDim2(0,-1,0,0); ThemeColor = 'Accent'; ZIndex = z+1; Parent = objs.background; }) objs.topBorder2 = utility:Draw('Square', { ThemeColor = 'Accent'; ZIndex = z+1; Parent = objs.background; }) objs.textlabel = utility:Draw('Text', { Position = newUDim2(.0425,0,0,-7); ThemeColor = 'Primary Text'; Size = 13; Font = 2; ZIndex = z+1; Parent = objs.background; }) objs.optionholder = utility:Draw('Square',{ Size = newUDim2(1-.03,0,1,-15); Position = newUDim2(.015,0,0,13); Transparency = 0; ZIndex = z+1; Parent = objs.background; }) end ---------------------- function section:SetText(text) self.text = tostring(text); self.objects.textlabel.Text = self.text; local x = self.objects.background.Object.Size.X - self.objects.textlabel.TextBounds.X - 13 self.objects.topBorder2.Size = newUDim2(0, x, 0, 1) self.objects.topBorder2.Position = newUDim2(1, 1 + -x, 0, 0) end function section:UpdateOptions() table.sort(self.options, function(a,b) return a.order < b.order end) local ySize, padding = 15, 0; for i,option in next, self.options do option.objects.holder.Visible = option.enabled if option.enabled then option.objects.holder.Position = newUDim2(0,0,0,ySize-15); ySize += option.objects.holder.Object.Size.Y + padding; end end self.objects.background.Size = newUDim2(1,0,0,ySize); end function section:SetEnabled(bool) if typeof(bool) == 'boolean' then section.enabled = bool; tab:UpdateSections(); end end ------- Options ------- -- // Toggle function section:AddToggle(data) local toggle = { class = 'toggle'; flag = data.flag; text = ''; tooltip = ''; order = #self.options+1; state = false; risky = false; callback = function() end; enabled = true; options = {}; objects = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) ~= toggle[i] ~= nil then toggle[i] = v end end table.insert(self.options, toggle) if toggle.flag then library.flags[toggle.flag] = toggle.state; library.options[toggle.flag] = toggle; end --- Create Objects --- do local objs = toggle.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,17); Transparency = 0; ZIndex = z+5; Parent = section.objects.optionholder; }) objs.background = utility:Draw('Square', { Size = newUDim2(0,8,0,8); Position = newUDim2(0,2,0,4); ThemeColor = 'Option Background'; ZIndex = z+3; Parent = objs.holder; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp45; Transparency = .25; ZIndex = z+4; Parent = objs.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+2; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z+1; Parent = objs.border1; }) objs.text = utility:Draw('Text', { Position = newUDim2(0,19,0,1); ThemeColor = 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = objs.holder; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = toggle.state and 'Accent' or 'Option Border 1'; end) utility:Connection(objs.holder.MouseButton1Down, function() toggle:SetState(not toggle.state); end) end ---------------------- function toggle:SetState(bool, nocallback) if typeof(bool) == 'boolean' then self.state = bool; if self.flag then library.flags[self.flag] = bool; end self.objects.border1.ThemeColor = bool and 'Accent' or (self.objects.holder.Hover and 'Accent' or 'Option Border 1'); self.objects.text.ThemeColor = bool and (self.risky and 'Risky Text Enabled' or 'Option Text 1') or (self.risky and 'Risky Text' or 'Option Text 3'); self.objects.background.ThemeColor = bool and 'Accent' or 'Option Background'; self.objects.background.ThemeColorOffset = bool and -55 or 0 if not nocallback then self.callback(bool); end end end function toggle:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; end end function toggle:UpdateOptions() table.sort(self.options, function(a,b) return a.order < b.order end) local x, y = 0, 0 for i,option in next, self.options do option.objects.holder.Visible = option.enabled if option.enabled then if option.class == 'color' or option.class == 'bind' then option.objects.holder.Position = newUDim2(1,-option.objects.holder.Object.Size.X-x,0,0); x = x + option.objects.holder.Object.Size.X; elseif option.class == 'slider' or option.class == 'list' then option.objects.holder.Position = newUDim2(0,0,1,-option.objects.holder.Object.Size.Y-y); y = y + option.objects.holder.Object.Size.Y; end end end self.objects.holder.Size = newUDim2(1,0,0,17 + y); section:UpdateOptions() end -- // Toggle Addons function toggle:AddColor(data) local color = { class = 'color'; flag = data.flag; text = ''; tooltip = ''; order = #self.options+1; callback = function() end; color = Color3.new(1,1,1); trans = 0; open = false; enabled = true; objects = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) and color[i] ~= nil then color[i] = v end end table.insert(self.options, color) if color.flag then library.flags[color.flag] = color.color; library.options[color.flag] = color; end --- Create Objects --- do local objs = color.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(0,21,0,17); Transparency = 0; ZIndex = z+6; Parent = self.objects.holder; }) objs.background = utility:Draw('Square', { Size = newUDim2(0,15,0,8); Position = newUDim2(0,4,0,5); ZIndex = z+3; Parent = objs.holder; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp45; Transparency = .25; ZIndex = z+4; Parent = objs.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+2; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z+1; Parent = objs.border1; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = color.state and 'Accent' or 'Option Border 1'; end) utility:Connection(objs.holder.MouseButton1Down, function() color:SetOpen(not color.open); end) end ---------------------- function color:SetColor(c3, nocallback) if typeof(c3) == 'Color3' then local h,s,v = c3:ToHSV(); c3 = fromhsv(h, clamp(s,.005,.995), clamp(v,.005,.995)) self.color = c3; self.objects.background.Color = c3; if not nocallback then self.callback(c3, self.trans); end if self.open then window.colorpicker:Visualize(self.color, self.trans); end if self.flag then library.flags[self.flag] = c3; end end end function color:SetTrans(trans, nocallback) if typeof(trans) == 'number' then self.trans = trans; if not nocallback then self.callback(self.color, trans); end if self.open then window.colorpicker:Visualize(self.color, self.trans); end end end function color:SetOpen(bool) if typeof(bool) == 'boolean' then self.open = bool if bool then if window.colorpicker.selected then window.colorpicker.selected.open = false; end window.colorpicker.selected = color window.colorpicker.objects.background.Parent = self.objects.background; window.colorpicker.objects.background.Visible = true; window.colorpicker:Visualize(color.color, color.trans) elseif window.colorpicker.selected == color then window.colorpicker.selected = nil; window.colorpicker.objects.background.Parent = window.objects.background; window.colorpicker.objects.background.Visible = false; end end end tooltip(color); color:SetColor(color.color, true); color:SetTrans(color.trans, true); self:UpdateOptions(); return color end function toggle:AddBind(data) local bind = { class = 'bind'; flag = data.flag; text = ''; tooltip = ''; bind = 'none'; mode = 'toggle'; order = #self.options+1; callback = function() end; keycallback = function() end; indicatorValue = library.keyIndicator:AddValue({value = 'value', key = 'key', enabled = false}); noindicator = false; invertindicator = false; state = false; nomouse = false; enabled = true; binding = false; objects = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) and bind[i] ~= nil then bind[i] = v end end table.insert(self.options, bind) if bind.flag then library.options[bind.flag] = bind; end if bind.bind == 'none' then bind.state = true if bind.flag then library.flags[bind.flag] = bind.state; end bind.callback(true) local display = bind.state; if bind.invertindicator then display = not bind.state; end bind.indicatorValue:SetEnabled(display and not bind.noindicator); bind.indicatorValue:SetKey((bind.text == nil or bind.text == '') and (bind.flag == nil and 'unknown' or bind.flag) or bind.text); -- this is so dumb bind.indicatorValue:SetValue('[Always]'); end --- Create Objects --- do local objs = bind.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(0,0,0,17); Transparency = 0; ZIndex = z+6; Parent = self.objects.holder; }) objs.keyText = utility:Draw('Text', { ThemeColor = 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+1; Parent = objs.holder; }) utility:Connection(objs.holder.MouseEnter, function() objs.keyText.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.keyText.ThemeColor = bind.binding and 'Accent' or 'Option Text 3'; end) utility:Connection(objs.holder.MouseButton1Down, function() if not bind.binding then bind:SetKeyText('...'); bind.binding = true; end end) end ---------------------- local c function bind:SetBind(keybind) if c then c:Disconnect(); if bind.flag then library.flags[bind.flag] = false; end bind.callback(false); end local keyName = 'NONE' self.bind = (keybind and keybind) or keybind or self.bind if self.bind == Enum.KeyCode.Backspace then self.bind = 'none'; bind.state = true if bind.flag then library.flags[bind.flag] = bind.state; end self.callback(true) local display = bind.state; if bind.invertindicator then display = not bind.state; end bind.indicatorValue:SetEnabled(display and not bind.noindicator); else keyName = keyNames[keybind] or keybind.Name or keybind end if self.bind ~= 'none' then bind.state = false if bind.flag then library.flags[bind.flag] = bind.state; end self.callback(false) local display = bind.state; if bind.invertindicator then display = not bind.state; end bind.indicatorValue:SetEnabled(display and not bind.noindicator); end self.keycallback(self.bind); self:SetKeyText(keyName:upper()); self.indicatorValue:SetKey((self.text == nil or self.text == '') and (self.flag == nil and 'unknown' or self.flag) or self.text); -- this is so dumb self.indicatorValue:SetValue('['..keyName:upper()..']'); if self.bind == 'none' then self.indicatorValue:SetValue('[Always]'); end self.objects.keyText.ThemeColor = self.objects.holder.Hover and 'Accent' or 'Option Text 3'; end function bind:SetKeyText(str) str = tostring(str); self.objects.keyText.Text = '['..str..']'; self.objects.keyText.Position = newUDim2(0, 2, 0, 2); self.objects.holder.Size = newUDim2(0,self.objects.keyText.TextBounds.X+2,0,17) toggle:UpdateOptions(); end utility:Connection(inputservice.InputBegan, function(inp) if inputservice:GetFocusedTextBox() then return elseif bind.binding then local key = (table.find({Enum.UserInputType.MouseButton1, Enum.UserInputType.MouseButton2, Enum.UserInputType.MouseButton3}, inp.UserInputType) and not bind.nomouse) and inp.UserInputType bind:SetBind(key or (not table.find(blacklistedKeys, inp.KeyCode)) and inp.KeyCode) bind.binding = false elseif not bind.binding and self.bind == 'none' then bind.state = true library.flags[bind.flag] = bind.state local display = bind.state; if bind.invertindicator then display = not bind.state; end bind.indicatorValue:SetEnabled(display and not bind.noindicator) elseif (inp.KeyCode == bind.bind or inp.UserInputType == bind.bind) and not bind.binding then if bind.mode == 'toggle' then bind.state = not bind.state if bind.flag then library.flags[bind.flag] = bind.state; end bind.callback(bind.state) local display = bind.state; if bind.invertindicator then display = not bind.state; end bind.indicatorValue:SetEnabled(display and not bind.noindicator); elseif bind.mode == 'hold' then if bind.flag then library.flags[bind.flag] = true; end bind.indicatorValue:SetEnabled((not bind.invertindicator and true or false) and not bind.noindicator); c = utility:Connection(runservice.RenderStepped, function() if bind.callback then bind.callback(true); end end) end end end) utility:Connection(inputservice.InputEnded, function(inp) if bind.bind ~= 'none' then if inp.KeyCode == bind.bind or inp.UserInputType == bind.bind then if c then c:Disconnect(); if bind.flag then library.flags[bind.flag] = false; end if bind.callback then bind.callback(false); end bind.indicatorValue:SetEnabled(bind.invertindicator and true or false); end end end end) tooltip(bind); bind:SetBind(bind.bind); self:UpdateOptions(); return bind end function toggle:AddSlider(data) local slider = { class = 'slider'; flag = data.flag; suffix = ''; tooltip = ''; order = #self.options+1; value = 0; min = 0; max = 100; increment = 1; callback = function() end; enabled = true; dragging = false; focused = false; objects = {}; }; local blacklist = {'objects', 'dragging'}; for i,v in next, data do if not table.find(blacklist, i) and (slider[i] ~= nil and typeof(slider[i]) == typeof(v)) then slider[i] = v; end end table.insert(self.options, slider) if slider.flag then library.flags[slider.flag] = slider.value; library.options[slider.flag] = slider; end --- Create Objects --- do local objs = slider.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,20); Transparency = 0; ZIndex = z+6; Parent = toggle.objects.holder; }) objs.background = utility:Draw('Square', { Size = newUDim2(1,-4,1,-8); Position = newUDim2(0,2,0,4); ThemeColor = 'Option Background'; ZIndex = z+2; Parent = objs.holder; }) objs.slider = utility:Draw('Square', { Size = newUDim2(0,0,1,0); ThemeColor = 'Accent'; ZIndex = z+3; Parent = objs.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.border1; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp90; Transparency = .65; ZIndex = z+4; Parent = objs.background; }) objs.text = utility:Draw('Text', { Position = newUDim2(.5,0,0,-1); ThemeColor = 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+5; Outline = true; Center = true; Parent = objs.background; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = slider.dragging and 'Accent' or 'Option Border 1'; end) local c; local inputNumber = ''; utility:Connection(slider.objects.holder.MouseButton1Down, function() if inputservice:IsKeyDown(Enum.KeyCode.LeftControl) then if slider.focused then slider.focused = false; c:Disconnect(); else objs.text.Text = tostring(slider.value)..tostring(slider.suffix)..'/'..tostring(slider.max)..tostring(slider.suffix)..' []'; slider.focused = true; inputNumber = ''; c = utility:Connection(inputservice.InputBegan, function(inp) if library.numberStrings[inp.KeyCode.Name] then local number = library.numberStrings[inp.KeyCode.Name]; inputNumber = inputNumber..tostring(number); objs.text.Text = string.format("%.14g", slider.value) .. tostring(slider.suffix) .. "/" .. slider.max .. tostring(slider.suffix) .. " [" .. inputNumber .. "]"; elseif inp.KeyCode == Enum.KeyCode.Backspace then inputNumber = inputNumber:sub(1,-2); objs.text.Text = string.format("%.14g", slider.value)..tostring(slider.suffix)..'/'..slider.max..tostring(slider.suffix)..' ['..inputNumber..']'; elseif inp.KeyCode == Enum.KeyCode.Return then slider:SetValue(tonumber(inputNumber)) slider.focused = false; c:Disconnect(); elseif inp.KeyCode == Enum.KeyCode.Escape then slider:SetValue(slider.value, true) slider.focused = false; c:Disconnect(); end end) end else slider.dragging = true; library.draggingSlider = slider; end end) utility:Connection(button1up, function() objs.border1.ThemeColor = objs.holder.Hover and 'Accent' or 'Option Border 1'; slider.dragging = false; library.draggingSlider = nil; end) end ---------------------- function slider:SetValue(value, nocallback) if typeof(value) == 'number' then local newValue = clamp(self.increment * floor(value/self.increment), self.min, self.max); local size, pos = self.objects.slider.Size, self.objects.slider.Position; if self.min >= 0 then size = newUDim2((newValue - self.min) / (self.max - self.min), 0, 1, 0); else size = newUDim2(newValue / (self.max - self.min), 0, 1, 0); pos = newUDim2((0 - self.min) / (self.max - self.min), 0, 0, 0); end utility:Tween(self.objects.slider, 'Size', size, .05, Enum.EasingDirection.Out, Enum.EasingStyle.Quad); utility:Tween(self.objects.slider, 'Position', pos, .05, Enum.EasingDirection.Out, Enum.EasingStyle.Quad); self.value = newValue; library.flags[self.flag] = newValue; self.objects.text.Text = string.format("%.14g",newValue)..tostring(self.suffix)..'/'..self.max..tostring(self.suffix); self.objects.text.ThemeColor = (self.min < 0 and newValue == 0 or newValue == self.min) and (self.risky and 'Risky Text' or 'Option Text 3') or (self.risky and 'Risky Text Enabled' or 'Option Text 1'); if not nocallback then self.callback(newValue); end end end tooltip(slider); slider:SetValue(slider.value, true); self:UpdateOptions(); return slider end function toggle:AddList(data) local list = { class = 'list'; flag = data.flag; text = ''; selected = ''; tooltip = ''; order = #self.options+1; callback = function() end; enabled = true; multi = false; open = false; values = {}; objects = {}; } table.insert(self.options, list); local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) ~= list[i] ~= nil then list[i] = v end end if list.flag then library.flags[list.flag] = list.selected; library.options[list.flag] = list; end -- Create Objects -- do local objs = list.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,22); Transparency = 0; ZIndex = z+6; Parent = toggle.objects.holder; }) objs.background = utility:Draw('Square', { Size = newUDim2(1,-4,1,-8); Position = newUDim2(0,2,0,4); ThemeColor = 'Option Background'; ZIndex = z+2; Parent = objs.holder; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.border1; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp90; Transparency = .65; ZIndex = z+4; Parent = objs.background; }) objs.inputText = utility:Draw('Text', { Position = newUDim2(0,4,0,0); ThemeColor = 'Option Text 2'; Text = 'none', Size = 13; Font = 2; ZIndex = z+5; Outline = true; Parent = objs.background; }) objs.openText = utility:Draw('Text', { Position = newUDim2(1,-10,0,0); ThemeColor = 'Option Text 3'; Text = '+'; Size = 13; Font = 2; ZIndex = z+5; Outline = true; Parent = objs.background; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = 'Option Border 1'; end) utility:Connection(objs.holder.MouseButton1Down, function() if list.open then list.open = false; objs.openText.Text = '+'; if window.dropdown.selected == list then window.dropdown.selected = nil; window.dropdown.objects.background.Visible = false; end else if window.dropdown.selected ~= nil then window.dropdown.selected.open = false end list.open = true; objs.openText.Text = '-'; window.dropdown.selected = list; window.dropdown.objects.background.Visible = true; window.dropdown.objects.background.Parent = objs.holder; window.dropdown:Refresh(); end end) end -------------------- function list:Select(option, nocallback) option = typeof(option) == 'table' and (self.multi == true and option or (#option == 0 and nil or option[1])) or self.multi == true and {option} or option; if option ~= nil then self.selected = option; local text = typeof(option) == 'table' and (#option == 0 and "none" or table.concat(option, ', ')) or tostring(option); local label = self.objects.inputText label.Text = text; if label.TextBounds.X > self.objects.background.Object.Size.X - 10 then local split = text:split(''); for i = 1,#split do label.Text = table.concat(split, '', 1, i) if label.TextBounds.X > self.objects.background.Object.Size.X - 10 then label.Text = label.Text:sub(1,-6)..'...'; break end end end if self.flag then library.flags[self.flag] = self.selected end if not nocallback then self.callback(self.selected); end end end function list:AddValue(value) table.insert(list.values, tostring(value)); if window.dropdown.selected == list then window.dropdown:Refresh() end end function list:RemoveValue(value) if table.find(list.values, value) then table.remove(list.values, table.find(list.values, value)); if window.dropdown.selected == list then window.dropdown:Refresh() end end end function list:ClearValues() table.clear(list.values); if window.dropdown.selected == list then window.dropdown:Refresh() end end tooltip(list); list:Select((data.value or data.selected) or (list.multi and 'none' or list.values[1]), true); self:UpdateOptions(); return list end tooltip(toggle); toggle:SetText(toggle.text); toggle:SetState(toggle.state, true); self:UpdateOptions(); return toggle end -- // Slider function section:AddSlider(data) local slider = { class = 'slider'; flag = data.flag; text = ''; tooltip = ''; suffix = ''; order = #self.options+1; value = 0; min = 0; max = 100; increment = 1; callback = function() end; enabled = true; dragging = false; focused = false; risky = false; objects = {}; }; local blacklist = {'objects', 'dragging'}; for i,v in next, data do if not table.find(blacklist, i) and (slider[i] ~= nil and typeof(slider[i]) == typeof(v)) then slider[i] = v; end end table.insert(self.options, slider) if slider.flag then library.flags[slider.flag] = slider.value; library.options[slider.flag] = slider; end --- Create Objects --- do local objs = slider.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,32); Transparency = 0; ZIndex = z+4; Parent = section.objects.optionholder; }) objs.background = utility:Draw('Square', { Size = newUDim2(1,-4,0,11); Position = newUDim2(0,2,1,-14); ThemeColor = 'Option Background'; ZIndex = z+2; Parent = objs.holder; }) objs.slider = utility:Draw('Square', { Size = newUDim2(0,0,1,0); ThemeColor = 'Accent'; ZIndex = z+3; Parent = objs.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.border1; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp90; Transparency = .65; ZIndex = z+4; Parent = objs.background; }) objs.text = utility:Draw('Text', { Position = newUDim2(0,2,0,1); ThemeColor = 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = objs.holder; }) objs.plusDetector = utility:Draw('Square', { Size = newUDim2(0,14,0,14); Position = newUDim2(1,-28,0,1); Transparency = 0; ZIndex = z+5; Parent = objs.holder; }) objs.minusDetector = utility:Draw('Square', { Size = newUDim2(0,14,0,14); Position = newUDim2(1,-14,0,1); Transparency = 0; ZIndex = z+5; Parent = objs.holder; }) objs.plusText = utility:Draw('Text', { Position = newUDim2(.5,0,0,-1); ThemeColor = 'Option Text 3'; Text = '+'; Size = 13; Font = 2; ZIndex = z+4; Center = true; Outline = true; Parent = objs.plusDetector; }) objs.minusText = utility:Draw('Text', { Position = newUDim2(.5,0,0,-1); ThemeColor = 'Option Text 3'; Text = '-'; Size = 13; Font = 2; ZIndex = z+4; Center = true; Outline = true; Parent = objs.minusDetector; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = slider.dragging and 'Accent' or 'Option Border 1'; end) utility:Connection(slider.objects.plusDetector.MouseButton1Down,function() slider:SetValue(slider.value + (inputservice:IsKeyDown(Enum.KeyCode.LeftShift) and 10 or slider.increment)) end) utility:Connection(slider.objects.minusDetector.MouseButton1Down,function() slider:SetValue(slider.value - (inputservice:IsKeyDown(Enum.KeyCode.LeftShift) and 10 or slider.increment)) end) local c; local inputNumber = ''; utility:Connection(slider.objects.holder.MouseButton1Down, function() if inputservice:IsKeyDown(Enum.KeyCode.LeftControl) then if slider.focused then slider.focused = false; c:Disconnect(); else objs.text.Text = slider.text..': '..tostring(slider.value)..tostring(slider.suffix)..' []'; slider.focused = true; inputNumber = ''; c = utility:Connection(inputservice.InputBegan, function(inp) if library.numberStrings[inp.KeyCode.Name] then local number = library.numberStrings[inp.KeyCode.Name]; inputNumber = inputNumber..tostring(number); objs.text.Text = slider.text..': '..string.format("%.14g",slider.value)..tostring(slider.suffix)..' ['..inputNumber..']'; elseif inp.KeyCode == Enum.KeyCode.Backspace then inputNumber = inputNumber:sub(1,-2); objs.text.Text = slider.text..': '..string.format("%.14g",slider.value)..tostring(slider.suffix)..' ['..inputNumber..']'; elseif inp.KeyCode == Enum.KeyCode.Return then slider:SetValue(tonumber(inputNumber)) slider.focused = false; c:Disconnect(); elseif inp.KeyCode == Enum.KeyCode.Escape then slider:SetValue(slider.value, true) slider.focused = false; c:Disconnect(); end end) end else slider.dragging = true; library.draggingSlider = slider; end end) utility:Connection(button1up, function() objs.border1.ThemeColor = objs.holder.Hover and 'Accent' or 'Option Border 1'; slider.dragging = false; library.draggingSlider = nil; end) end ---------------------- function slider:SetValue(value, nocallback) if typeof(value) == 'number' then local newValue = clamp(self.increment * floor(value/self.increment), self.min, self.max); local size, pos = self.objects.slider.Size, self.objects.slider.Position; if self.min >= 0 then size = newUDim2((newValue - self.min) / (self.max - self.min), 0, 1, 0); else size = newUDim2(newValue / (self.max - self.min), 0, 1, 0); pos = newUDim2((0 - self.min) / (self.max - self.min), 0, 0, 0); end utility:Tween(self.objects.slider, 'Size', size, .05, Enum.EasingDirection.Out, Enum.EasingStyle.Quad); utility:Tween(self.objects.slider, 'Position', pos, .05, Enum.EasingDirection.Out, Enum.EasingStyle.Quad); self.value = newValue; library.flags[self.flag] = newValue; self.objects.text.Text = slider.text..': '..string.format("%.14g",newValue)..tostring(self.suffix); self.objects.text.ThemeColor = (self.min < 0 and newValue == 0 or newValue == self.min) and (self.risky and 'Risky Text' or 'Option Text 3') or (self.risky and 'Risky Text Enabled' or 'Option Text 1'); if not nocallback then self.callback(newValue); end end end function slider:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str..': '..tostring(self.value)..tostring(self.suffix); end end tooltip(slider); slider:SetText(slider.text); slider:SetValue(slider.value, true); self:UpdateOptions(); return slider end -- // Button function section:AddButton(data) local button = { class = 'button'; flag = data.flag; text = ''; suffix = ''; tooltip = ''; order = #self.options+1; callback = function() end; confirm = false; enabled = true; risky = false; objects = {}; subbuttons = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) and button[i] ~= nil then button[i] = v; end end table.insert(self.options, button) if button.flag then library.options[button.flag] = button; end --- Create Objects --- do local objs = button.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,22); Transparency = 0; ZIndex = z+4; Parent = section.objects.optionholder; }) objs.background = utility:Draw('Square', { Size = newUDim2(1,-4,0,14); Position = newUDim2(0,2,0,4); ThemeColor = 'Option Background'; ZIndex = z+2; Parent = objs.holder; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.border1; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp90; Transparency = .65; ZIndex = z+3; Parent = objs.background; }) objs.text = utility:Draw('Text', { Position = newUDim2(.5,0,0,0); ThemeColor = 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+4; Outline = true; Center = true; Parent = objs.background; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = 'Option Border 1'; objs.text.ThemeColor = self.risky and 'Risky Text' or 'Option Text 3'; objs.background.ThemeColor = 'Option Background'; objs.background.ThemeColorOffset = 0; end) utility:Connection(objs.holder.MouseButton1Up, function() objs.text.ThemeColor = self.risky and 'Risky Text' or 'Option Text 3'; objs.background.ThemeColor = 'Option Background'; objs.background.ThemeColorOffset = 0; end) local clicked, counting = false, false utility:Connection(objs.holder.MouseButton1Down, function() objs.text.ThemeColor = self.risky and 'Risky Text Enabled' or 'Option Text 2'; objs.background.ThemeColor = 'Accent'; objs.background.ThemeColorOffset = -95; task.spawn(function() -- this is ugly and i do not care :) if button.confirm then if clicked then clicked = false counting = false objs.text.Text = button.text button.callback() else clicked = true counting = true for i = 3,1,-1 do if not counting then break end objs.text.Text = 'Confirm '..button.text..'? '..tostring(i) wait(1) end clicked = false counting = false objs.text.Text = button.text end else button.callback() end end) end) end ---------------------- function button:AddButton(data) local button = { class = 'button'; flag = data.flag; text = ''; suffix = ''; tooltip = ''; order = #self.subbuttons+1; callback = function() end; confirm = false; enabled = true; objects = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) and button[i] ~= nil then button[i] = v; end end table.insert(self.subbuttons, button) if button.flag then library.options[button.flag] = button; end --- Create Objects --- do local objs = button.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,1,0); Transparency = 0; ZIndex = z+5; Parent = self.objects.holder; }) objs.background = utility:Draw('Square', { Size = newUDim2(1,-4,1,-8); Position = newUDim2(0,2,0,4); ThemeColor = 'Option Background'; ZIndex = z+2; Parent = objs.holder; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.border1; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp90; Transparency = .65; ZIndex = z+3; Parent = objs.background; }) objs.text = utility:Draw('Text', { Position = newUDim2(.5,0,0,0); ThemeColor = 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+4; Outline = true; Center = true; Parent = objs.background; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = 'Option Border 1'; objs.text.ThemeColor = self.risky and 'Risky Text' or 'Option Text 3'; objs.background.ThemeColor = 'Option Background'; objs.background.ThemeColorOffset = 0; end) utility:Connection(objs.holder.MouseButton1Up, function() objs.text.ThemeColor = self.risky and 'Risky Text' or 'Option Text 3'; objs.background.ThemeColor = 'Option Background'; objs.background.ThemeColorOffset = 0; end) local clicked, counting = false, false utility:Connection(objs.holder.MouseButton1Down, function() objs.text.ThemeColor = self.risky and 'Risky Text Enabled' or 'Option Text 2'; objs.background.ThemeColor = 'Accent'; objs.background.ThemeColorOffset = -95; task.spawn(function() -- this is ugly and i do not care :) if button.confirm then if clicked then clicked = false counting = false objs.text.Text = button.text button.callback() else clicked = true counting = true for i = 3,1,-1 do if not counting then break end objs.text.Text = 'Confirm '..button.text..'? '..tostring(i) wait(1) end clicked = false counting = false objs.text.Text = button.text end else button.callback() end end) end) end ---------------------- function button:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; end end tooltip(button); button:SetText(button.text); self:UpdateOptions(); return button end ---------------------- function button:UpdateOptions() -- this so dumb XD local buttons = 1 + #self.subbuttons; local buttonSize = (1 / buttons) - .005; self.objects.background.Size = newUDim2(buttonSize,-4,0,14); for i,v in next, self.subbuttons do v.objects.holder.Size = newUDim2(buttonSize,0,1,0); v.objects.holder.Position = newUDim2(i * buttonSize + .01, 0, 0, 0) end end function button:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; end end tooltip(button); button:SetText(button.text); self:UpdateOptions(); return button end -- // Separator function section:AddSeparator(data) local separator = { class = 'separator'; flag = data.flag; text = ''; order = #self.options+1; enabled = true; objects = {}; }; local blacklist = {'objects', 'dragging'}; for i,v in next, data do if not table.find(blacklist, i) and (separator[i] ~= nil and typeof(separator[i]) == typeof(v)) then separator[i] = v; end end table.insert(self.options, separator) --- Create Objects --- do local objs = separator.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,18); Transparency = 0; ZIndex = z; Parent = section.objects.optionholder; }) objs.line1 = utility:Draw('Square', { Position = newUDim2(0,0,0,1); ThemeColor = 'Option Background'; ZIndex = z+1; Parent = objs.holder; }) objs.line2 = utility:Draw('Square', { Position = newUDim2(0,0,0,1); ThemeColor = 'Option Background'; ZIndex = z+1; Parent = objs.holder; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.line1; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.line2; }) objs.text = utility:Draw('Text', { Position = newUDim2(.5,0,0,1); ThemeColor = 'Option Text 2'; Size = 13; Font = 2; ZIndex = z; Outline = true; Center = true; Parent = objs.holder; }) end ---------------------- function separator:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; local xScale = ( 1- utility:ConvertNumberRange(self.objects.text.TextBounds.X, 0, self.objects.holder.Object.Size.X, 0, 1)) / 2 - (str == '' and 0 or .04) self.objects.line1.Size = newUDim2(xScale, 0, 0, 1) self.objects.line2.Size = newUDim2(xScale, 0, 0, 1) self.objects.line1.Position = newUDim2(0,1,.5,-1) self.objects.line2.Position = newUDim2(1 - self.objects.line2.Size.X.Scale,-1,.5,-1) end end separator:SetText(separator.text); self:UpdateOptions(); return separator end -- // Color Picker function section:AddColor(data) local color = { class = 'color'; flag = data.flag; text = ''; tooltip = ''; order = #self.options+1; callback = function() end; color = Color3.new(1,1,1); trans = 0; open = false; enabled = true; risky = false; objects = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) and color[i] ~= nil then color[i] = v end end table.insert(self.options, color) if color.flag then library.flags[color.flag] = color.color; library.options[color.flag] = color; end --- Create Objects --- do local objs = color.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,19); Transparency = 0; ZIndex = z+5; Parent = section.objects.optionholder; }) objs.background = utility:Draw('Square', { Size = newUDim2(0,15,0,8); Position = newUDim2(1,-16,0,5); ZIndex = z+3; Parent = objs.holder; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp45; Transparency = .25; ZIndex = z+4; Parent = objs.background; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+2; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z+1; Parent = objs.border1; }) objs.text = utility:Draw('Text', { Position = newUDim2(0,2,0,2); ThemeColor = color.risky and 'Risky Text Enabled' or 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = objs.holder; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = color.state and 'Accent' or 'Option Border 1'; end) utility:Connection(objs.holder.MouseButton1Down, function() color:SetOpen(not color.open); end) end ---------------------- function color:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; end end function color:SetColor(c3, nocallback) if typeof(c3) == 'Color3' then local h,s,v = c3:ToHSV(); c3 = fromhsv(h, clamp(s,.005,.995), clamp(v,.005,.995)); self.color = c3; self.objects.background.Color = c3; if not nocallback then self.callback(c3, self.trans); end if self.open then window.colorpicker:Visualize(self.color, self.trans); end if self.flag then library.flags[self.flag] = c3; end end end function color:SetTrans(trans, nocallback) if typeof(trans) == 'number' then self.trans = trans; if not nocallback then self.callback(self.color, trans); end if self.open then window.colorpicker:Visualize(self.color, self.trans); end end end function color:SetOpen(bool) if typeof(bool) == 'boolean' then self.open = bool if bool then if window.colorpicker.selected then window.colorpicker.selected.open = false; end window.colorpicker.selected = color window.colorpicker.objects.background.Parent = self.objects.background; window.colorpicker.objects.background.Visible = true; window.colorpicker:Visualize(color.color, color.trans) elseif window.colorpicker.selected == color then window.colorpicker.selected = nil; window.colorpicker.objects.background.Parent = window.objects.background; window.colorpicker.objects.background.Visible = false; end end end tooltip(color); color:SetText(color.text); color:SetColor(color.color, true); color:SetTrans(color.trans, true); self:UpdateOptions(); return color end -- // Text Box function section:AddBox(data) local box = { class = 'box'; flag = data.flag; text = ''; input = ''; order = #self.options+1; callback = function() end; enabled = true; focused = false; risky = false; objects = {}; }; local blacklist = {'objects', 'dragging'}; for i,v in next, data do if not table.find(blacklist, i) and box[i] ~= nil then box[i] = v; end end table.insert(self.options, box) if box.flag then library.flags[box.flag] = box.input; library.options[box.flag] = box; end --- Create Objects --- do local objs = box.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,37); Transparency = 0; ZIndex = z+4; Parent = section.objects.optionholder; }) objs.background = utility:Draw('Square', { Size = newUDim2(1,-4,0,15); Position = newUDim2(0,2,1,-17); ThemeColor = 'Option Background'; ZIndex = z+2; Parent = objs.holder; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.border1; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp90; Transparency = .65; ZIndex = z+4; Parent = objs.background; }) objs.text = utility:Draw('Text', { Position = newUDim2(0,2,0,2); ThemeColor = box.risky and 'Risky Text Enabled' or 'Option Text 2'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = objs.holder; }) objs.inputText = utility:Draw('Text', { Position = newUDim2(0,2,0,0); ThemeColor = 'Option Text 2'; Size = 13; Font = 2; ZIndex = z+5; Outline = true; Parent = objs.background; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = 'Option Border 1'; end) utility:Connection(objs.holder.MouseButton1Down, function() if box.focused then box:ReleaseFocus(); actionservice:UnbindAction('FreezeMovement'); else actionservice:BindAction( 'FreezeMovement', function() return Enum.ContextActionResult.Sink end, false, unpack(Enum.PlayerActions:GetEnumItems()) ) box:CaptureFocus(inputservice:IsKeyDown(Enum.KeyCode.LeftControl)); if inputservice:IsKeyDown(Enum.KeyCode.LeftControl) then objs.inputText.Text = ''; end end end) end ---------------------- function box:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; end end function box:SetInput(str, nocallback) if typeof(str) == 'string' then self.input = str; self.objects.inputText.Text = str; if not nocallback then self.callback(str); end if self.flag then library.flags[self.flag] = str; end end end local c local input = box.input; function box:CaptureFocus(clear) box.focused = true if clear then input = ''; end self.objects.inputText.ThemeColor = 'Option Text 1'; c = utility:Connection(inputservice.InputBegan, function(inp) if inp.KeyCode == Enum.KeyCode.Return or inp.UserInputType == Enum.UserInputType.MouseButton1 then box:ReleaseFocus(true); elseif inp.KeyCode == Enum.KeyCode.Escape then input = self.input self.objects.inputText.Text = input; box:ReleaseFocus(); elseif inp.KeyCode == Enum.KeyCode.Backspace then input = input:sub(1,-2); self.objects.inputText.Text = input; elseif #inp.KeyCode.Name == 1 or table.find(whitelistedBoxKeys, inp.KeyCode) or inp.KeyCode.Name == 'Space' or inp.KeyCode.Name == 'Minus' or inp.KeyCode.Name == 'Equals' or inp.KeyCode.Name == 'Backquote' then local wlIdx = table.find(whitelistedBoxKeys, inp.KeyCode) local keyString = inp.KeyCode.Name == 'Space' and ' ' or inp.KeyCode.Name == 'Minus' and '_' or inp.KeyCode.Name == 'Equals' and '+' or inp.KeyCode.Name == 'Backquote' and '~' or wlIdx ~= nil and tostring(wlIdx-1) or inp.KeyCode.Name if not (inputservice:IsKeyDown(Enum.KeyCode.LeftShift) and not inputservice:IsKeyDown(Enum.KeyCode.RightShift)) then keyString = keyString:lower(); if inp.KeyCode.Name == 'Minus' then keyString = '-' elseif inp.KeyCode.Name == 'Equals' then keyString = '=' elseif inp.KeyCode.Name == 'Backquote' then keyString = '`' end else if keyString == '1' then keyString = '!' elseif keyString == '2' then keyString = '@' elseif keyString == '3' then keyString = '#' elseif keyString == '4' then keyString = '$' elseif keyString == '5' then keyString = '%' elseif keyString == '6' then keyString = '^' elseif keyString == '7' then keyString = '&' elseif keyString == '8' then keyString = '*' elseif keyString == '9' then keyString = '(' elseif keyString == '0' then keyString = ')' end end input = input..keyString; self.objects.inputText.Text = input; end end) end function box:ReleaseFocus(apply) box.focused = false; self.objects.inputText.ThemeColor = 'Option Text 2'; if apply then box:SetInput(input); end c:Disconnect(); end tooltip(box); box:SetText(box.text); box:SetInput(box.input, true); self:UpdateOptions(); return box end -- // Keybind function section:AddBind(data) local bind = { class = 'bind'; flag = data.flag; text = ''; tooltip = ''; bind = 'none'; mode = 'toggle'; order = #self.options+1; callback = function() end; keycallback = function() end; indicatorValue = library.keyIndicator:AddValue({value = 'value', key = 'key', enabled = false}); noindicator = false; state = false; nomouse = false; enabled = true; binding = false; risky = false; objects = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) and bind[i] ~= nil then bind[i] = v end end table.insert(self.options, bind) if bind.flag then library.options[bind.flag] = bind; end --- Create Objects --- do local objs = bind.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,19); Transparency = 0; ZIndex = z+5; Parent = section.objects.optionholder; }) objs.text = utility:Draw('Text', { Position = newUDim2(0,2,0,2); ThemeColor = bind.risky and 'Risky Text' or 'Option Text 2'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = objs.holder; }) objs.keyText = utility:Draw('Text', { ThemeColor = 'Option Text 3'; Size = 13; Font = 2; ZIndex = z+1; Parent = objs.holder; }) utility:Connection(objs.holder.MouseEnter, function() objs.keyText.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.keyText.ThemeColor = bind.binding and 'Accent' or 'Option Text 3'; end) utility:Connection(objs.holder.MouseButton1Down, function() if not bind.binding then bind:SetKeyText('...'); bind.binding = true; end end) end ---------------------- local c function bind:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; self.indicatorValue:SetKey(str); end end function bind:SetBind(keybind) if c then c:Disconnect(); if bind.flag then library.flags[bind.flag] = false; end bind.callback(false); end local keyName = 'NONE' self.bind = (keybind and keybind) or keybind or self.bind if self.bind == Enum.KeyCode.Backspace then self.bind = 'none'; else keyName = keyNames[keybind] or keybind.Name or keybind end self.keycallback(self.bind); self:SetKeyText(keyName:upper()); self.indicatorValue:SetKey((self.text == nil or self.text == '') and (self.flag == nil and 'unknown' or self.flag) or self.text); -- this is so dumb self.indicatorValue:SetValue('['..keyName:upper()..']'); self.objects.keyText.ThemeColor = self.objects.holder.Hover and 'Accent' or 'Option Text 3'; end function bind:SetKeyText(str) str = tostring(str); self.objects.keyText.Text = '['..str..']'; self.objects.keyText.Position = newUDim2(1,-self.objects.keyText.TextBounds.X, 0, 2); end utility:Connection(inputservice.InputBegan, function(inp) if inputservice:GetFocusedTextBox() then return elseif bind.binding then local key = (table.find({Enum.UserInputType.MouseButton1, Enum.UserInputType.MouseButton2, Enum.UserInputType.MouseButton3}, inp.UserInputType) and not bind.nomouse) and inp.UserInputType bind:SetBind(key or (not table.find(blacklistedKeys, inp.KeyCode)) and inp.KeyCode) bind.binding = false elseif not bind.binding and self.bind == 'none' then bind.state = true library.flags[bind.flag] = bind.state elseif (inp.KeyCode == bind.bind or inp.UserInputType == bind.bind) and not bind.binding then if bind.mode == 'toggle' then bind.state = not bind.state if bind.flag then library.flags[bind.flag] = bind.state; end bind.callback(bind.state) bind.indicatorValue:SetEnabled(bind.state and not bind.noindicator); elseif bind.mode == 'hold' then if bind.flag then library.flags[bind.flag] = true; end bind.indicatorValue:SetEnabled(true and not bind.noindicator); c = utility:Connection(runservice.RenderStepped, function() bind.callback(true); end) end end end) utility:Connection(inputservice.InputEnded, function(inp) if bind.bind ~= 'none' then if inp.KeyCode == bind.bind or inp.UserInputType == bind.key then if c then c:Disconnect(); if bind.flag then library.flags[bind.flag] = false; end bind.callback(false); bind.indicatorValue:SetEnabled(false); end end end end) tooltip(bind); bind:SetBind(bind.bind); bind:SetText(bind.text); self:UpdateOptions(); return bind end -- // Dropdown function section:AddList(data) local list = { class = 'list'; flag = data.flag; text = ''; selected = ''; tooltip = ''; order = #self.options+1; callback = function() end; enabled = true; multi = false; open = false; risky = false; values = {}; objects = {}; } table.insert(self.options, list); local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) ~= list[i] ~= nil then list[i] = v end end if list.flag then library.flags[list.flag] = list.selected; library.options[list.flag] = list; end -- Create Objects -- do local objs = list.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Size = newUDim2(1,0,0,40); Transparency = 0; ZIndex = z+4; Parent = section.objects.optionholder; }) objs.background = utility:Draw('Square', { Size = newUDim2(1,-4,0,15); Position = newUDim2(0,2,1,-19); ThemeColor = 'Option Background'; ZIndex = z+2; Parent = objs.holder; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 1'; ZIndex = z+1; Parent = objs.background; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Option Border 2'; ZIndex = z; Parent = objs.border1; }) objs.gradient = utility:Draw('Image', { Size = newUDim2(1,0,1,0); Data = library.images.gradientp90; Transparency = .65; ZIndex = z+4; Parent = objs.background; }) objs.text = utility:Draw('Text', { Position = newUDim2(0,2,0,2); ThemeColor = list.risky and 'Risky Text Enabled' or 'Option Text 2'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = objs.holder; }) objs.inputText = utility:Draw('Text', { Position = newUDim2(0,4,0,0); ThemeColor = 'Option Text 2'; Text = 'none', Size = 13; Font = 2; ZIndex = z+5; Outline = true; Parent = objs.background; }) objs.openText = utility:Draw('Text', { Position = newUDim2(1,-10,0,0); ThemeColor = 'Option Text 3'; Text = '+'; Size = 13; Font = 2; ZIndex = z+5; Outline = true; Parent = objs.background; }) utility:Connection(objs.holder.MouseEnter, function() objs.border1.ThemeColor = 'Accent'; end) utility:Connection(objs.holder.MouseLeave, function() objs.border1.ThemeColor = 'Option Border 1'; end) utility:Connection(objs.holder.MouseButton1Down, function() if list.open then list.open = false; objs.openText.Text = '+'; if window.dropdown.selected == list then window.dropdown.selected = nil; window.dropdown.objects.background.Visible = false; end else if window.dropdown.selected ~= nil then window.dropdown.selected.open = false end list.open = true; objs.openText.Text = '-'; window.dropdown.selected = list; window.dropdown.objects.background.Visible = true; window.dropdown.objects.background.Parent = objs.holder; window.dropdown:Refresh(); end end) end -------------------- function list:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; end end function list:Select(option, nocallback) option = typeof(option) == 'table' and (self.multi == true and option or (#option == 0 and nil or option[1])) or self.multi == true and {option} or option; if option ~= nil then self.selected = option; local text = typeof(option) == 'table' and (#option == 0 and "none" or table.concat(option, ', ')) or tostring(option); local label = self.objects.inputText label.Text = text; if label.TextBounds.X > self.objects.background.Object.Size.X - 10 then local split = text:split(''); for i = 1,#split do label.Text = table.concat(split, '', 1, i) if label.TextBounds.X > self.objects.background.Object.Size.X - 10 then label.Text = label.Text:sub(1,-6)..'...'; break end end end if self.flag then library.flags[self.flag] = self.selected end if not nocallback then self.callback(self.selected); end end end function list:AddValue(value) table.insert(list.values, tostring(value)); if window.dropdown.selected == list then window.dropdown:Refresh() end end function list:RemoveValue(value) if table.find(list.values, value) then table.remove(list.values, table.find(list.values, value)); if window.dropdown.selected == list then window.dropdown:Refresh() end end end function list:ClearValues() table.clear(list.values); if window.dropdown.selected == list then window.dropdown:Refresh() end end tooltip(list); list:Select((data.value or data.selected) or (list.multi and 'none' or list.values[1]), true); list:SetText(list.text); self:UpdateOptions(); return list end -- Text function section:AddText(data) local text = { class = 'text'; flag = data.flag; text = ''; tooltip = ''; order = #self.options+1; enabled = true; risky = false; objects = {}; }; local blacklist = {'objects'}; for i,v in next, data do if not table.find(blacklist, i) and text[i] ~= nil then text[i] = v end end if data.flag then library.options[data.flag] = text; end table.insert(self.options, text) --- Create Objects --- do local objs = text.objects; local z = library.zindexOrder.window+25; objs.holder = utility:Draw('Square', { Transparency = 0; ZIndex = z+5; Parent = section.objects.optionholder; }) objs.text = utility:Draw('Text', { Position = newUDim2(0,2,0,2); ThemeColor = text.risky and 'Risky Text Enabled' or 'Option Text 2'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = objs.holder; }) end ---------------------- function text:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; self.objects.holder.Size = newUDim2(1,0,0,self.objects.text.TextBounds.Y + 6); section:UpdateOptions(); end end text:SetText(text.text); self:UpdateOptions(); return text end ----------------------- section:UpdateOptions(); section:SetText(section.text); self:UpdateSections(); return section; end function tab:UpdateSections() table.sort(self.sections, function(a,b) return a.order < b.order end) local last1,last2; local padding = 15; for _,section in next, self.sections do if section.objects.background.Visible ~= (section.enabled and tab.selected) then section.objects.background.Visible = section.enabled and tab.selected section:UpdateOptions(); end if section.enabled then if section.side == 1 then if last1 then section.objects.background.Position = last1.objects.background.Position + newUDim2(0,0,0,last1.objects.background.Object.Size.Y + padding); end last1 = section; elseif section.side == 2 then if last2 then section.objects.background.Position = last2.objects.background.Position + newUDim2(0,0,0,last2.objects.background.Object.Size.Y + padding); end last2 = section; end end section:SetText(section.text) end end function tab:SetText(str) if typeof(str) == 'string' then self.text = str; self.objects.text.Text = str; window:UpdateTabs(); end end function tab:Select() window.selectedTab = tab; window:UpdateTabs(); for i,v in next, window.tabs do if v.callback then v.callback(v == tab) end end end if window.selectedTab == nil then tab:Select(); end tab:SetText(tab.text); window:UpdateTabs(); return tab; end function window:UpdateTabs() table.sort(self.tabs, function(a,b) return a.order < b.order end) local pos = 0; for i,v in next, self.tabs do local objs = v.objects; v.selected = v == self.selectedTab; objs.background.ThemeColor = v.selected and 'Selected Tab Background' or 'Unselected Tab Background'; objs.background.Size = newUDim2(0, objs.text.TextBounds.X + 14, 1, v.selected and 1 or 0); objs.background.Position = newUDim2(0, pos, 0, 0) objs.text.ThemeColor = v.selected and 'Selected Tab Text' or 'Unselected Tab Text'; objs.text.Position = newUDim2(.5, 0, 0, 3); objs.topBorder.ThemeColor = v.selected and 'Accent' or 'Unselected Tab Background'; pos += objs.background.Size.X.Offset + 1 v:UpdateSections(); end end window:SetOpen(true); return window; end -- Tooltip do local z = library.zindexOrder.window + 2000; tooltipObjects.background = utility:Draw('Square', { ThemeColor = 'Group Background'; ZIndex = z; Visible = false; }) tooltipObjects.border1 = utility:Draw('Square', { Size = UDim2.new(1,2,1,2); Position = UDim2.new(0,-1,0,-1); ThemeColor = 'Border 1'; ZIndex = z-1; Parent = tooltipObjects.background; }) tooltipObjects.border2 = utility:Draw('Square', { Size = UDim2.new(1,4,1,4); Position = UDim2.new(0,-2,0,-2); ThemeColor = 'Border 3'; ZIndex = z-2; Parent = tooltipObjects.background; }) tooltipObjects.text = utility:Draw('Text', { Position = UDim2.new(0,3,0,0); ThemeColor = 'Primary Text'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = tooltipObjects.background; }) tooltipObjects.riskytext = utility:Draw('Text', { Position = UDim2.new(0,3,0,0); ThemeColor = 'Risky Text Enabled'; Text = '[RISKY]'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Parent = tooltipObjects.background; }) end -- Watermark do self.watermark = { objects = {}; text = { {"informant.wtf", true}, {"V"..getgenv().Config.Version, true}, {getgenv().luaguardvars.DiscordName, true}, {'0 fps', true}, {'0ms', true}, }; lock = 'custom'; position = newUDim2(0,0,0,0); refreshrate = 25; } function self.watermark:Update() self.objects.background.Visible = library.flags.watermark_enabled if library.flags.watermark_enabled then local date = {os.date('%b',os.time()), os.date('%d',os.time()), os.date('%Y',os.time())} local daySuffix = math.floor(date[2]%10) date[2] = date[2]..(daySuffix == 1 and 'st' or daySuffix == 2 and 'nd' or daySuffix == 3 and 'rd' or 'th') self.text[4][1] = library.stats.fps..' fps' self.text[5][1] = floor(library.stats.ping)..'ms' local text = {}; for _,v in next, self.text do if v[2] then table.insert(text, v[1]); end end self.objects.text.Text = table.concat(text,' | ') self.objects.background.Size = newUDim2(0, self.objects.text.TextBounds.X + 10, 0, 17) local size = self.objects.background.Object.Size; local screensize = workspace.CurrentCamera.ViewportSize; self.position = ( self.lock == 'Top Right' and newUDim2(0, screensize.X - size.X - 15, 0, 15) or self.lock == 'Top Left' and newUDim2(0, 15, 0, 15) or self.lock == 'Bottom Right' and newUDim2(0, screensize.X - size.X - 15, 0, screensize.Y - size.Y - 15) or self.lock == 'Bottom Left' and newUDim2(0, 15, 0, screensize.Y - size.Y - 15) or self.lock == 'Top' and newUDim2(0, screensize.X / 2 - size.X / 2, 0, 15) or newUDim2(library.flags.watermark_x / 100, 0, library.flags.watermark_y / 100, 0) ) self.objects.background.Position = self.position end end do local objs = self.watermark.objects; local z = self.zindexOrder.watermark; objs.background = utility:Draw('Square', { Visible = false; Size = newUDim2(0, 200, 0, 17); Position = newUDim2(0,800,0,100); ThemeColor = 'Background'; ZIndex = z; }) objs.border1 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 2'; Parent = objs.background; ZIndex = z-1; }) objs.border2 = utility:Draw('Square', { Size = newUDim2(1,2,1,2); Position = newUDim2(0,-1,0,-1); ThemeColor = 'Border 3'; Parent = objs.border1; ZIndex = z-2; }) objs.topbar = utility:Draw('Square', { Size = newUDim2(1,0,0,1); ThemeColor = 'Accent'; ZIndex = z+1; Parent = objs.background; }) objs.text = utility:Draw('Text', { Position = newUDim2(.5,0,0,2); ThemeColor = 'Primary Text'; Text = 'Watermark Text'; Size = 13; Font = 2; ZIndex = z+1; Outline = true; Center = true; Parent = objs.background; }) end end local lasttick = tick(); utility:Connection(runservice.RenderStepped, function(step) library.stats.fps = floor(1/step) library.stats.ping = stats.Network.ServerStatsItem["Data Ping"]:GetValue() library.stats.sendkbps = stats.DataSendKbps library.stats.receivekbps = stats.DataReceiveKbps if (tick()-lasttick)*1000 > library.watermark.refreshrate then lasttick = tick() library.watermark:Update() end end) self.keyIndicator = self.NewIndicator({title = 'Keybinds', pos = newUDim2(0,15,0,325), enabled = false}); self.targetIndicator = self.NewIndicator({title = 'Target Info', pos = newUDim2(0,15,0,350), enabled = false}); self.targetName = self.targetIndicator:AddValue({key = 'Name :', value = 'nil'}) self.targetDisplay = self.targetIndicator:AddValue({key = 'DName :', value = 'nil'}) self.targetHealth = self.targetIndicator:AddValue({key = 'Health :', value = '0'}) self.targetDistance = self.targetIndicator:AddValue({key = 'Distance :', value = '0m'}) self.targetTool = self.targetIndicator:AddValue({key = 'Weapon :', value = 'nil'}) self:SetTheme(library.theme); self:SetOpen(true); self.hasInit = true end function library:CreateSettingsTab(menu) local settingsTab = menu:AddTab('Settings', 999); local configSection = settingsTab:AddSection('Config', 2); local mainSection = settingsTab:AddSection('Main', 1); local creditsSection = settingsTab:AddSection('Credits', 2); creditsSection:AddSeparator({text = 'Owners/Developers'}); creditsSection:AddText({text = "xz#1111"}) creditsSection:AddText({text = "goof#1000"}) creditsSection:AddSeparator({text = 'Helpers'}); creditsSection:AddText({text = "encode#9999"}) creditsSection:AddText({text = "Vault#5434"}) configSection:AddBox({text = 'Config Name', flag = 'configinput'}) configSection:AddList({text = 'Config', flag = 'selectedconfig'}) local function refreshConfigs() library.options.selectedconfig:ClearValues(); for _,v in next, listfiles(self.cheatname..'/'..self.gamename..'/configs') do local ext = '.'..v:split('.')[#v:split('.')]; if ext == self.fileext then library.options.selectedconfig:AddValue(v:split('\\')[#v:split('\\')]:sub(1,-#ext-1)) end end end configSection:AddButton({text = 'Load', confirm = false, callback = function() library:LoadConfig(library.flags.selectedconfig); end}):AddButton({text = 'Save', confirm = true, callback = function() library:SaveConfig(library.flags.selectedconfig); end}) configSection:AddButton({text = 'Create', confirm = false, callback = function() if library.flags.configinput == "" then return end if library:GetConfig(library.flags.configinput) then return end writefile(self.cheatname..'/'..self.gamename..'/configs/'..library.flags.configinput.. self.fileext, http:JSONEncode({})); refreshConfigs() end}):AddButton({text = 'Delete', confirm = true, callback = function() if library:GetConfig(library.flags.selectedconfig) then delfile(self.cheatname..'/'..self.gamename..'/configs/'..library.flags.selectedconfig.. self.fileext); refreshConfigs() end end}) refreshConfigs() mainSection:AddBind({text = 'Open / Close', flag = 'togglebind', nomouse = true, noindicator = true, bind = Enum.KeyCode.RightShift, callback = function() library:SetOpen(not library.open) end}); mainSection:AddToggle({text = 'Disable Movement If Open', flag = 'disablemenumovement', callback = function(bool) if bool and library.open then actionservice:BindAction( 'FreezeMovement', function() return Enum.ContextActionResult.Sink end, false, unpack(Enum.PlayerActions:GetEnumItems()) ) else actionservice:UnbindAction('FreezeMovement'); end end}) mainSection:AddButton({text = 'Join Discord', flag = 'joindiscord', confirm = true, callback = function() local res = http_request({ Url = 'http://127.0.0.1:6463/rpc?v=1', Method = 'POST', Headers = { ['Content-Type'] = 'application/json', Origin = 'https://discord.com' }, Body = game:GetService('HttpService'):JSONEncode({ cmd = 'INVITE_BROWSER', nonce = game:GetService('HttpService'):GenerateGUID(false), args = {code = getgenv().Config.Invite} }) }) end}) mainSection:AddButton({text = 'Copy Discord', flag = 'copydiscord', callback = function() setclipboard('https://discord.gg/'..getgenv().Config.Invite) end}) mainSection:AddButton({text = 'Rejoin Server', confirm = true, callback = function() game:GetService("TeleportService"):TeleportToPlaceInstance(game.PlaceId, game.JobId); end}) mainSection:AddButton({text = 'Copy Join Script', callback = function() setclipboard(([[game:GetService("TeleportService"):TeleportToPlaceInstance(%s, "%s")]]):format(game.PlaceId, game.JobId)) end}) mainSection:AddButton({text = 'Unload', confirm = true, callback = function() library:Unload(); end}) mainSection:AddSeparator({text = 'Keybinds'}); mainSection:AddToggle({text = 'Keybind Indicator', flag = 'keybind_indicator', callback = function(bool) library.keyIndicator:SetEnabled(bool); end}) mainSection:AddSlider({text = 'Position X', flag = 'keybind_indicator_x', min = 0, max = 100, increment = .1, value = .5, callback = function() library.keyIndicator:SetPosition(newUDim2(library.flags.keybind_indicator_x / 100, 0, library.flags.keybind_indicator_y / 100, 0)); end}); mainSection:AddSlider({text = 'Position Y', flag = 'keybind_indicator_y', min = 0, max = 100, increment = .1, value = 35, callback = function() library.keyIndicator:SetPosition(newUDim2(library.flags.keybind_indicator_x / 100, 0, library.flags.keybind_indicator_y / 100, 0)); end}); mainSection:AddSeparator({text = 'Watermark'}) mainSection:AddToggle({text = 'Enabled', flag = 'watermark_enabled'}); mainSection:AddList({text = 'Position', flag = 'watermark_pos', selected = 'Custom', values = {'Top', 'Top Left', 'Top Right', 'Bottom Left', 'Bottom Right', 'Custom'}, callback = function(val) library.watermark.lock = val; end}) mainSection:AddSlider({text = 'Custom X', flag = 'watermark_x', suffix = '%', value = 6.1, min = 0, max = 100, increment = .1}); mainSection:AddSlider({text = 'Custom Y', flag = 'watermark_y', suffix = '%', value = 1.2, min = 0, max = 100, increment = .1}); local themeStrings = {}; for _,v in next, library.themes do table.insert(themeStrings, v.name) end local themeSection = settingsTab:AddSection('Theme', 1); local setByPreset = false themeSection:AddList({text = 'Presets', flag = 'preset_theme', values = themeStrings, callback = function(newTheme) setByPreset = true for _,v in next, library.themes do if v.name == newTheme then for x, d in pairs(library.options) do if v.theme[tostring(x)] ~= nil then d:SetColor(v.theme[tostring(x)]) end end library:SetTheme(v.theme) break end end setByPreset = false end}):Select('Default'); return settingsTab; end getgenv().library = library return library