null nil false Sorter print("Special thanks to Bitl, Carrot, iago, winsupermario1234, Khangaroo, drslicendice, coke, TheLivingBee, Raymonf, and a bunch of play - testers for help making 2012 fully stable and work. 8)") script.Playerlist:clone().Parent = game.StarterGui script.Dialogs:clone().Parent = game.StarterGui script.Backpack:clone().Parent = game.StarterGui script.Health:clone().Parent = game.StarterGui script.Menu:clone().Parent = game.StarterGui script.ReenableDialogScript:clone().Parent = game.Lighting script.TimeoutScript:clone().Parent = game.Lighting script.ResetCommand:clone().Parent = game.Workspace script.Chat:clone().Parent = game.StarterGui script.Notifications.Parent = game.StarterGui script:remove() Backpack false 4288914085 1 4279970357 1 false false ControlFrame 0 0 0 0 1 0 1 0 0 0 true 1 false 4288914085 1 4279970357 1 false false NotificationBox 1 -200 0.5 0 0 200 0.419999987 0 0 true 1 false BackpackBuilder -- fixed by iagoMAO#6808, any bugs report to me. -- --rbxsig%ajqqTypn8cXmAlrdqhDKhItl413ndYEkpVdn/u7NGTmEyfwlhOJeSdZIZE+QLG/vRLkbVlp75MyPeWt7MR7K443uOfLnmRnXvj0XdhY0HQxdqVu9uRh1FvpjhLVWE3p9GRv2Vh99QxI/FUC0rDcT64cNueM8fjBp7QpFypJ1R+8=% --rbxassetid%53878047% -- This script creates almost all gui elements found in the backpack (warning: there are a lot!) -- TODO: automate this process local gui = script.Parent -- A couple of necessary functions local function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end end local function waitForProperty(instance, property) while not instance[property] do instance.Changed:wait() end end local function IsTouchDevice() -- local touchEnabled = false -- pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end) -- return touchEnabled end local function IsPhone() --if gui.AbsoluteSize.Y <= 320 then --- return true -- end -- return false end waitForChild(game,"Players") waitForProperty(game.Players,"LocalPlayer") local player = game.Players.LocalPlayer -- First up is the current loadout local CurrentLoadout = Instance.new("Frame") CurrentLoadout.Name = "CurrentLoadout" CurrentLoadout.Position = UDim2.new(0.5, -300, 1, -85) CurrentLoadout.Size = UDim2.new(0, 600, 0, 54) CurrentLoadout.BackgroundTransparency = 1 --CurrentLoadout.RobloxLocked = true CurrentLoadout.Parent = gui local CLBackground = Instance.new('ImageLabel') CLBackground.Name = 'Background'; CLBackground.Size = UDim2.new(1.2, 0, 1.2, 0); CLBackground.Image = "http://www.roblox.com/asset/?id=96536002" CLBackground.BackgroundTransparency = 1.0; CLBackground.Position = UDim2.new(-0.1, 0, -0.1, 0); CLBackground.ZIndex = 0.0; CLBackground.Parent = CurrentLoadout CLBackground.Visible = true local BackgroundUp = Instance.new('ImageLabel') BackgroundUp.Size = UDim2.new(1, 0, 0.025, 1) BackgroundUp.Position = UDim2.new(0, 0, 0, 0) BackgroundUp.Image = 'http://www.roblox.com/asset/?id=97662207' BackgroundUp.BackgroundTransparency = 1.0 BackgroundUp.Parent = CLBackground local Debounce = Instance.new("BoolValue") Debounce.Name = "Debounce" --Debounce.RobloxLocked = true Debounce.Parent = CurrentLoadout local BackpackButton = Instance.new("ImageButton") --BackpackButton.RobloxLocked = true BackpackButton.Visible = true BackpackButton.Name = "BackpackButton" BackpackButton.BackgroundTransparency = 1 BackpackButton.Image = "http://www.roblox.com/asset/?id=97617958" BackpackButton.Position = UDim2.new(0.5, -60, 1, -108) BackpackButton.Size = UDim2.new(0, 120, 0, 18) waitForChild(gui,"ControlFrame") BackpackButton.Parent = gui.ControlFrame local NumSlots = 9 for i = 0, NumSlots do local slotFrame = Instance.new("Frame") -- slotFrame.RobloxLocked = true slotFrame.BackgroundColor3 = Color3.new(0,0,0) slotFrame.BackgroundTransparency = 1 slotFrame.BorderColor3 = Color3.new(1, 1, 1) slotFrame.Name = "Slot" .. tostring(i) slotFrame.ZIndex = 4.0 if i == 0 then slotFrame.Position = UDim2.new(0.9, 0, 0, 0) else slotFrame.Position = UDim2.new((i - 1) * 0.1, (i-1)* 6,0,0) end slotFrame.Size = UDim2.new(0, 54, 1, 0) slotFrame.Parent = CurrentLoadout end local TempSlot = Instance.new("ImageButton") TempSlot.Name = "TempSlot" TempSlot.Active = true TempSlot.Size = UDim2.new(1,0,1,0) TempSlot.BackgroundTransparency = 1.0 TempSlot.Style = 'Custom' TempSlot.Visible = false --TempSlot.RobloxLocked = true TempSlot.Parent = CurrentLoadout TempSlot.ZIndex = 4.0 local slotBackground = Instance.new('ImageLabel') slotBackground.Name = 'Background' slotBackground.BackgroundTransparency = 1.0 slotBackground.Image = 'http://www.roblox.com/asset/?id=97613075' slotBackground.Size = UDim2.new(1, 0, 1, 0) slotBackground.Parent = TempSlot local HighLight = Instance.new('ImageLabel') HighLight.Name = 'Highlight' HighLight.BackgroundTransparency = 1.0 HighLight.Image = 'http://www.roblox.com/asset/?id=97643886' HighLight.Size = UDim2.new(1, 0, 1, 0) --HighLight.Parent = TempSlot HighLight.Visible = false -- TempSlot Children local GearReference = Instance.new("ObjectValue") GearReference.Name = "GearReference" --GearReference.RobloxLocked = true GearReference.Parent = TempSlot local ToolTipLabel = Instance.new("TextLabel") ToolTipLabel.Name = "ToolTipLabel" -- ToolTipLabel.RobloxLocked = true ToolTipLabel.Text = "" ToolTipLabel.BackgroundTransparency = 0.5 ToolTipLabel.BorderSizePixel = 0 ToolTipLabel.Visible = false ToolTipLabel.TextColor3 = Color3.new(1,1,1) ToolTipLabel.BackgroundColor3 = Color3.new(0,0,0) ToolTipLabel.TextStrokeTransparency = 0 ToolTipLabel.Font = Enum.Font.ArialBold ToolTipLabel.FontSize = Enum.FontSize.Size14 --ToolTipLabel.TextWrap = true ToolTipLabel.Size = UDim2.new(1,60,0,20) ToolTipLabel.Position = UDim2.new(0,-30,0,-30) ToolTipLabel.Parent = TempSlot local Kill = Instance.new("BoolValue") Kill.Name = "Kill" -- Kill.RobloxLocked = true Kill.Parent = TempSlot local GearImage = Instance.new("ImageLabel") GearImage.Name = "GearImage" GearImage.BackgroundTransparency = 1 GearImage.Position = UDim2.new(0, 0, 0, 0) GearImage.Size = UDim2.new(1, 0, 1, 0) GearImage.ZIndex = 5.0 -- GearImage.RobloxLocked = true GearImage.Parent = TempSlot local SlotNumber = Instance.new("TextLabel") SlotNumber.Name = "SlotNumber" SlotNumber.BackgroundTransparency = 1 SlotNumber.BorderSizePixel = 0 SlotNumber.Font = Enum.Font.ArialBold SlotNumber.FontSize = Enum.FontSize.Size18 SlotNumber.Position = UDim2.new(0, 0, 0, 0) SlotNumber.Size = UDim2.new(0,10,0,15) SlotNumber.TextColor3 = Color3.new(1,1,1) SlotNumber.TextTransparency = 0 SlotNumber.TextXAlignment = Enum.TextXAlignment.Left SlotNumber.TextYAlignment = Enum.TextYAlignment.Bottom -- SlotNumber.RobloxLocked = true SlotNumber.Parent = TempSlot SlotNumber.ZIndex = 5 local SlotNumberDownShadow = SlotNumber:Clone() SlotNumberDownShadow.Name = "SlotNumberDownShadow" SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0) SlotNumberDownShadow.Position = UDim2.new(0, 1, 0, -1) SlotNumberDownShadow.Parent = TempSlot SlotNumberDownShadow.ZIndex = 2 local SlotNumberUpShadow = SlotNumberDownShadow:Clone() SlotNumberUpShadow.Name = "SlotNumberUpShadow" SlotNumberUpShadow.Position = UDim2.new(0, -1, 0, -1) SlotNumberUpShadow.Parent = TempSlot local GearText = Instance.new("TextLabel") -- GearText.RobloxLocked = true GearText.Name = "GearText" GearText.BackgroundTransparency = 1 GearText.Font = Enum.Font.Arial GearText.FontSize = Enum.FontSize.Size14 GearText.Position = UDim2.new(0,-8,0,-8) GearText.Size = UDim2.new(1,16,1,16) GearText.Text = "" GearText.TextColor3 = Color3.new(1,1,1) GearText.TextWrap = true GearText.Parent = TempSlot GearText.ZIndex = 5.0 --- Great, now lets make the inventory! local Backpack = Instance.new("Frame") --Backpack.RobloxLocked = true Backpack.Visible = false Backpack.Name = "Backpack" Backpack.Position = UDim2.new(0.5, 0, 0.5, 0) Backpack.BackgroundColor3 = Color3.new(32/255, 32/255, 32/255) Backpack.BackgroundTransparency = 0.0 Backpack.BorderSizePixel = 0 Backpack.Parent = gui Backpack.Active = true -- Backpack Children local SwapSlot = Instance.new("BoolValue") -- SwapSlot.RobloxLocked = true SwapSlot.Name = "SwapSlot" SwapSlot.Parent = Backpack -- SwapSlot Children local Slot = Instance.new("IntValue") -- Slot.RobloxLocked = true Slot.Name = "Slot" Slot.Parent = SwapSlot local GearButton = Instance.new("ObjectValue") -- GearButton.RobloxLocked = true GearButton.Name = "GearButton" GearButton.Parent = SwapSlot --[[local Tabs = Instance.new("Frame") Tabs.Name = "Tabs" Tabs.Visible = false Tabs.Active = false -- Tabs.RobloxLocked = true Tabs.BackgroundColor3 = Color3.new(0,0,0) Tabs.BackgroundTransparency = 0.08 Tabs.BorderSizePixel = 0 Tabs.Position = UDim2.new(0,0,-0.1,-4) Tabs.Size = UDim2.new(1,0,0.1,4) Tabs.Parent = Backpack -- Tabs Children local tabLine = Instance.new("Frame") -- tabLine.RobloxLocked = true tabLine.Name = "TabLine" tabLine.BackgroundColor3 = Color3.new(53/255, 53/255, 53/255) tabLine.BorderSizePixel = 0 tabLine.Position = UDim2.new(0,5,1,-4) tabLine.Size = UDim2.new(1,-10,0,4) tabLine.ZIndex = 2 tabLine.Parent = Tabs local InventoryButton = Instance.new("TextButton") -- InventoryButton.RobloxLocked = true InventoryButton.Name = "InventoryButton" InventoryButton.Size = UDim2.new(0,60,0,30) InventoryButton.Position = UDim2.new(0,7,1,-31) InventoryButton.BackgroundColor3 = Color3.new(1,1,1) InventoryButton.BorderColor3 = Color3.new(1,1,1) InventoryButton.Font = Enum.Font.ArialBold InventoryButton.FontSize = Enum.FontSize.Size18 InventoryButton.Text = "Gear" InventoryButton.AutoButtonColor = false InventoryButton.TextColor3 = Color3.new(0,0,0) InventoryButton.Selected = true InventoryButton.Active = true InventoryButton.ZIndex = 3 InventoryButton.Parent = Tabs local closeButton = Instance.new("TextButton") -- closeButton.RobloxLocked = true closeButton.Name = "CloseButton" closeButton.Font = Enum.Font.ArialBold closeButton.FontSize = Enum.FontSize.Size24 closeButton.Position = UDim2.new(1,-33,0,4) closeButton.Size = UDim2.new(0,30,0,30) closeButton.Style = Enum.ButtonStyle.RobloxButton closeButton.Text = "" closeButton.TextColor3 = Color3.new(1,1,1) closeButton.Parent = Tabs closeButton.Modal = true --closeButton child local XImage = Instance.new("ImageLabel") -- XImage.RobloxLocked = true XImage.Name = "XImage" game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75547445") XImage.Image = "http://www.roblox.com/asset/?id=75547445" --TODO: move to rbxasset XImage.BackgroundTransparency = 1 XImage.Position = UDim2.new(-.25,-1,-.25,-1) XImage.Size = UDim2.new(1.5,2,1.5,2) XImage.ZIndex = 2 XImage.Parent = closeButton--]] -- Generic Search gui used across backpack local SearchFrame = Instance.new("Frame") -- SearchFrame.RobloxLocked = true SearchFrame.Name = "SearchFrame" SearchFrame.BackgroundTransparency = 1 SearchFrame.Position = UDim2.new(1,-220,0,2) SearchFrame.Size = UDim2.new(0,220,0,24) SearchFrame.Parent = Backpack -- SearchFrame Children local SearchButton = Instance.new("ImageButton") -- SearchButton.RobloxLocked = true SearchButton.Name = "SearchButton" SearchButton.Size = UDim2.new(0,25,0,25) SearchButton.BackgroundTransparency = 1 SearchButton.Image = "rbxasset://textures/ui/SearchIcon.png" SearchButton.Parent = SearchFrame local SearchBoxFrame = Instance.new("TextButton") -- SearchBoxFrame.RobloxLocked = true SearchBoxFrame.Position = UDim2.new(0,25,0,0) SearchBoxFrame.Size = UDim2.new(1,-28,0,26) SearchBoxFrame.Name = "SearchBoxFrame" SearchBoxFrame.Text = "" SearchBoxFrame.Style = Enum.ButtonStyle.RobloxButton SearchBoxFrame.Parent = SearchFrame -- SearchBoxFrame Children local SearchBox = Instance.new("TextBox") -- SearchBox.RobloxLocked = true SearchBox.Name = "SearchBox" SearchBox.BackgroundTransparency = 1 SearchBox.Font = Enum.Font.ArialBold SearchBox.FontSize = Enum.FontSize.Size12 SearchBox.Position = UDim2.new(0,-5,0,-5) SearchBox.Size = UDim2.new(1,10,1,10) SearchBox.TextColor3 = Color3.new(1,1,1) SearchBox.TextXAlignment = Enum.TextXAlignment.Left SearchBox.ZIndex = 2 SearchBox.TextWrap = true SearchBox.Text = "Search..." SearchBox.Parent = SearchBoxFrame local ResetButton = Instance.new("TextButton") -- ResetButton.RobloxLocked = true ResetButton.Visible = false ResetButton.Name = "ResetButton" ResetButton.Position = UDim2.new(1,-26,0,3) ResetButton.Size = UDim2.new(0,20,0,20) ResetButton.Style = Enum.ButtonStyle.RobloxButtonDefault ResetButton.Text = "X" ResetButton.TextColor3 = Color3.new(1,1,1) ResetButton.Font = Enum.Font.ArialBold ResetButton.FontSize = Enum.FontSize.Size18 ResetButton.ZIndex = 3 ResetButton.Parent = SearchFrame ------------------------------- GEAR ------------------------------------------------------- local Gear = Instance.new("Frame") Gear.Name = "Gear" -- Gear.RobloxLocked = true Gear.BackgroundTransparency = 1 Gear.Size = UDim2.new(1,0,1,0) Gear.Parent = Backpack -- Gear Children local AssetsList = Instance.new("Frame") -- AssetsList.RobloxLocked = true AssetsList.Name = "AssetsList" AssetsList.BackgroundTransparency = 1 AssetsList.Size = UDim2.new(0.2,0,1,0) AssetsList.Style = Enum.FrameStyle.RobloxSquare AssetsList.Visible = false AssetsList.Parent = Gear local GearGrid = Instance.new("Frame") -- GearGrid.RobloxLocked = true GearGrid.Name = "GearGrid" GearGrid.Size = UDim2.new(0.95, 0, 1, 0) GearGrid.BackgroundTransparency = 1 GearGrid.Parent = Gear local GearButton = Instance.new("ImageButton") -- GearButton.RobloxLocked = true GearButton.Visible = false GearButton.Name = "GearButton" GearButton.Size = UDim2.new(0, 54, 0, 54) GearButton.Style = 'Custom' GearButton.Parent = GearGrid GearButton.BackgroundTransparency = 1.0 local slotBackground = Instance.new('ImageLabel') slotBackground.Name = 'Background' slotBackground.BackgroundTransparency = 1.0 slotBackground.Image = 'http://www.roblox.com/asset/?id=97613075' slotBackground.Size = UDim2.new(1, 0, 1, 0) slotBackground.Parent = GearButton -- GearButton Children local GearReference = Instance.new("ObjectValue") -- GearReference.ed = true GearReference.Name = "GearReference" GearReference.Parent = GearButton local GreyOutButton = Instance.new("Frame") -- GreyOutButton.RobloxLocked = true GreyOutButton.Name = "GreyOutButton" GreyOutButton.BackgroundTransparency = 0.5 GreyOutButton.Size = UDim2.new(1,0,1,0) GreyOutButton.Active = true GreyOutButton.Visible = false GreyOutButton.ZIndex = 3 GreyOutButton.Parent = GearButton local GearText = Instance.new("TextLabel") -- GearText.RobloxLocked = true GearText.Name = "GearText" GearText.BackgroundTransparency = 1 GearText.Font = Enum.Font.Arial GearText.FontSize = Enum.FontSize.Size14 GearText.Position = UDim2.new(0,-8,0,-8) GearText.Size = UDim2.new(1,16,1,16) GearText.Text = "" GearText.ZIndex = 2 GearText.TextColor3 = Color3.new(1,1,1) GearText.TextWrap = true GearText.Parent = GearButton local GearGridScrollingArea = Instance.new("Frame") --GearGridScrollingArea.RobloxLocked = true GearGridScrollingArea.Name = "GearGridScrollingArea" GearGridScrollingArea.Position = UDim2.new(1, -19, 0, 35) GearGridScrollingArea.Size = UDim2.new(0, 17, 1, -45) GearGridScrollingArea.BackgroundTransparency = 1 GearGridScrollingArea.Parent = Gear local GearLoadouts = Instance.new("Frame") --GearLoadouts.RobloxLocked = true GearLoadouts.Name = "GearLoadouts" GearLoadouts.BackgroundTransparency = 1 GearLoadouts.Position = UDim2.new(0.7,23,0.5,1) GearLoadouts.Size = UDim2.new(0.3,-23,0.5,-1) GearLoadouts.Parent = Gear GearLoadouts.Visible = false -- GearLoadouts Children local GearLoadoutsHeader = Instance.new("Frame") --GearLoadoutsHeader.RobloxLocked = true GearLoadoutsHeader.Name = "GearLoadoutsHeader" GearLoadoutsHeader.BackgroundColor3 = Color3.new(0,0,0) GearLoadoutsHeader.BackgroundTransparency = 0.2 GearLoadoutsHeader.BorderColor3 = Color3.new(1,0,0) GearLoadoutsHeader.Size = UDim2.new(1,2,0.15,-1) GearLoadoutsHeader.Parent = GearLoadouts -- GearLoadoutsHeader Children local LoadoutsHeaderText = Instance.new("TextLabel") --LoadoutsHeaderText.RobloxLocked = true LoadoutsHeaderText.Name = "LoadoutsHeaderText" LoadoutsHeaderText.BackgroundTransparency = 1 LoadoutsHeaderText.Font = Enum.Font.ArialBold LoadoutsHeaderText.FontSize = Enum.FontSize.Size18 LoadoutsHeaderText.Size = UDim2.new(1,0,1,0) LoadoutsHeaderText.Text = "Loadouts" LoadoutsHeaderText.TextColor3 = Color3.new(1,1,1) LoadoutsHeaderText.Parent = GearLoadoutsHeader local GearLoadoutsScrollingArea = GearGridScrollingArea:clone() GearLoadoutsScrollingArea.Name = "GearLoadoutsScrollingArea" GearLoadoutsScrollingArea.Position = UDim2.new(1,-15,0.15,2) GearLoadoutsScrollingArea.Size = UDim2.new(0,17,0.85,-2) GearLoadoutsScrollingArea.Parent = GearLoadouts local LoadoutsList = Instance.new("Frame") LoadoutsList.Name = "LoadoutsList" LoadoutsList.Position = UDim2.new(0,0,0.15,2) LoadoutsList.Size = UDim2.new(1,-17,0.85,-2) LoadoutsList.Style = Enum.FrameStyle.RobloxSquare LoadoutsList.Parent = GearLoadouts local GearPreview = Instance.new("Frame") GearPreview.Name = "GearPreview" GearPreview.Position = UDim2.new(0.7,23,0,0) GearPreview.Size = UDim2.new(0.3,-28,0.5,-1) GearPreview.BackgroundTransparency = 1 GearPreview.ZIndex = 7 GearPreview.Parent = Gear -- GearPreview Children local GearStats = Instance.new("Frame") GearStats.Name = "GearStats" GearStats.BackgroundTransparency = 1 GearStats.Position = UDim2.new(0,0,0.75,0) GearStats.Size = UDim2.new(1,0,0.25,0) GearStats.ZIndex = 8 GearStats.Parent = GearPreview -- GearStats Children local GearName = Instance.new("TextLabel") GearName.Name = "GearName" GearName.BackgroundTransparency = 1 GearName.Font = Enum.Font.ArialBold GearName.FontSize = Enum.FontSize.Size18 GearName.Position = UDim2.new(0,-3,0,0) GearName.Size = UDim2.new(1,6,1,5) GearName.Text = "" GearName.TextColor3 = Color3.new(1,1,1) GearName.TextWrap = true GearName.ZIndex = 9 GearName.Parent = GearStats local GearImage = Instance.new("ImageLabel") GearImage.Name = "GearImage" GearImage.Image = "" GearImage.BackgroundTransparency = 1 GearImage.Position = UDim2.new(0.125,0,0,0) GearImage.Size = UDim2.new(0.75,0,0.75,0) GearImage.ZIndex = 8 GearImage.Parent = GearPreview --GearImage Children local GearIcons = Instance.new("Frame") GearIcons.BackgroundColor3 = Color3.new(0,0,0) GearIcons.BackgroundTransparency = 0.5 GearIcons.BorderSizePixel = 0 GearIcons.Name = "GearIcons" GearIcons.Position = UDim2.new(0.4,2,0.85,-2) GearIcons.Size = UDim2.new(0.6,0,0.15,0) GearIcons.Visible = false GearIcons.ZIndex = 9 GearIcons.Parent = GearImage -- GearIcons Children local GenreImage = Instance.new("ImageLabel") GenreImage.Name = "GenreImage" GenreImage.BackgroundColor3 = Color3.new(102/255,153/255,1) GenreImage.BackgroundTransparency = 0.5 GenreImage.BorderSizePixel = 0 GenreImage.Size = UDim2.new(0.25,0,1,0) GenreImage.Parent = GearIcons local AttributeOneImage = GenreImage:clone() AttributeOneImage.Name = "AttributeOneImage" AttributeOneImage.BackgroundColor3 = Color3.new(1,51/255,0) AttributeOneImage.Position = UDim2.new(0.25,0,0,0) AttributeOneImage.Parent = GearIcons local AttributeTwoImage = GenreImage:clone() AttributeTwoImage.Name = "AttributeTwoImage" AttributeTwoImage.BackgroundColor3 = Color3.new(153/255,1,153/255) AttributeTwoImage.Position = UDim2.new(0.5,0,0,0) AttributeTwoImage.Parent = GearIcons local AttributeThreeImage = GenreImage:clone() AttributeThreeImage.Name = "AttributeThreeImage" AttributeThreeImage.BackgroundColor3 = Color3.new(0,0.5,0.5) AttributeThreeImage.Position = UDim2.new(0.75,0,0,0) AttributeThreeImage.Parent = GearIcons false BackpackGear --rbxsig%IEUAo3Q1k4Rwb3ZcqPBum//j3+Jm/9Nv0JyCeCRWUrggWps7aG81/aPzlH9pPlMkkdsZwLsCRu6eTTrqzXn2DAJNPRs7y8akc3z91r1DP3jwomfpdT+2DBAmPk3Cdj8NXQzP6T+uEYm2kk2TW9pXonKvCgRVqXFx8J7mTr+aM1M=% --rbxassetid%45284430% local t = {} local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc) local eventConnection = nil --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away) local tryConnect = function() if game:IsAncestorOf(parentInstance) then --Entering the world, make sure we are connected/synced if not eventConnection then eventConnection = instance[event]:connect(signalFunc) if syncFunc then syncFunc() end end else --Probably leaving the world, so disconnect for now if eventConnection then eventConnection:disconnect() if removeFunc then removeFunc() end end end end --Hook it up to ancestryChanged signal local connection = parentInstance.AncestryChanged:connect(tryConnect) --Now connect us if we're already in the world tryConnect() return connection end local function getScreenGuiAncestor(instance) local localInstance = instance while localInstance and not localInstance:IsA("ScreenGui") do localInstance = localInstance.Parent end return localInstance end local function CreateButtons(frame, buttons, yPos, ySize) local buttonNum = 1 local buttonObjs = {} for i, obj in ipairs(buttons) do local button = Instance.new("TextButton") button.Name = "Button" .. buttonNum button.Font = Enum.Font.Arial button.FontSize = Enum.FontSize.Size18 button.AutoButtonColor = true button.Modal = true if obj["Style"] then button.Style = obj.Style else button.Style = Enum.ButtonStyle.RobloxButton end if obj["ZIndex"] then button.ZIndex = obj.ZIndex end button.Text = obj.Text button.TextColor3 = Color3.new(1,1,1) button.MouseButton1Click:connect(obj.Function) button.Parent = frame buttonObjs[buttonNum] = button buttonNum = buttonNum + 1 end local numButtons = buttonNum-1 if numButtons == 1 then frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset) elseif numButtons == 2 then frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset) frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset) frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset) elseif numButtons >= 3 then local spacing = .1 / numButtons local buttonSize = .9 / numButtons buttonNum = 1 while buttonNum <= numButtons do buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset) buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset) buttonNum = buttonNum + 1 end end end local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps) local newStep = steps - 1 --otherwise we really get one more step than we want local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X )) local wholeNum, remainder = math.modf(relativePosX * newStep) if remainder > 0.5 then wholeNum = wholeNum + 1 end relativePosX = wholeNum/newStep local result = math.ceil(relativePosX * newStep) if sliderPosition.Value ~= (result + 1) then --only update if we moved a step sliderPosition.Value = result + 1 slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end end local function cancelSlide(areaSoak) areaSoak.Visible = false if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end end t.CreateStyledMessageDialog = function(title, message, style, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0, 165) frame.Position = UDim2.new(0.25, 0, 0.5, -72.5) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local styleImage = Instance.new("ImageLabel") styleImage.Name = "StyleImage" styleImage.BackgroundTransparency = 1 styleImage.Position = UDim2.new(0,5,0,15) if style == "error" or style == "Error" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42565285" elseif style == "notify" or style == "Notify" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42604978" elseif style == "confirm" or style == "Confirm" then styleImage.Size = UDim2.new(0, 74, 0, 76) styleImage.Image = "http://www.roblox.com/asset/?id=42557901" else return t.CreateMessageDialog(title,message,buttons) end styleImage.Parent = frame local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.TextStrokeTransparency = 0 titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 80, 0, 0) titleLabel.Size = UDim2.new(1, -80, 0, 40) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextStrokeTransparency = 0 messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 80, 0, 45) messageLabel.Size = UDim2.new(0.95, -80, 0, 55) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) ) return frame end t.CreateMessageDialog = function(title, message, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0.5, 0) frame.Position = UDim2.new(0.25, 0, 0.25, 0) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 0, 0, 0) titleLabel.Size = UDim2.new(1, 0, 0.15, 0) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0) messageLabel.Size = UDim2.new(0.95, 0, .55, 0) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0)) return frame end t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ) local baseZIndex = 0 if (type(baseZ) == "number") then baseZIndex = baseZ end local width = UDim.new(0, 100) local height = UDim.new(0, 32) local xPos = 0.055 local frame = Instance.new("Frame") local textColor = Color3.new(1,1,1) if (whiteSkin) then textColor = Color3.new(0.5, 0.5, 0.5) end frame.Name = "DropDownMenu" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(width, height) local dropDownMenu = Instance.new("TextButton") dropDownMenu.Name = "DropDownMenuButton" dropDownMenu.TextWrap = true dropDownMenu.TextColor3 = textColor dropDownMenu.Text = "Choose One" dropDownMenu.Font = Enum.Font.ArialBold dropDownMenu.FontSize = Enum.FontSize.Size18 dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center dropDownMenu.BackgroundTransparency = 1 dropDownMenu.AutoButtonColor = true if (whiteSkin) then dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else dropDownMenu.Style = Enum.ButtonStyle.RobloxButton end dropDownMenu.Size = UDim2.new(1,0,1,0) dropDownMenu.Parent = frame dropDownMenu.ZIndex = 2 + baseZIndex local dropDownIcon = Instance.new("ImageLabel") dropDownIcon.Name = "Icon" dropDownIcon.Active = false if (whiteSkin) then dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png" dropDownIcon.Size = UDim2.new(0,16,0,12) dropDownIcon.Position = UDim2.new(1,-17,0.5, -6) else dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894" dropDownIcon.Size = UDim2.new(0,11,0,6) dropDownIcon.Position = UDim2.new(1,-11,0.5, -2) end dropDownIcon.BackgroundTransparency = 1 dropDownIcon.Parent = dropDownMenu dropDownIcon.ZIndex = 2 + baseZIndex local itemCount = #items local dropDownItemCount = #items local useScrollButtons = false if dropDownItemCount > 6 then useScrollButtons = true dropDownItemCount = 6 end local droppedDownMenu = Instance.new("TextButton") droppedDownMenu.Name = "List" droppedDownMenu.Text = "" droppedDownMenu.BackgroundTransparency = 1 --droppedDownMenu.AutoButtonColor = true if (whiteSkin) then droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton end droppedDownMenu.Visible = false droppedDownMenu.Active = true --Blocks clicks droppedDownMenu.Position = UDim2.new(0,0,0,0) droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0) droppedDownMenu.Parent = frame droppedDownMenu.ZIndex = 2 + baseZIndex local choiceButton = Instance.new("TextButton") choiceButton.Name = "ChoiceButton" choiceButton.BackgroundTransparency = 1 choiceButton.BorderSizePixel = 0 choiceButton.Text = "ReplaceMe" choiceButton.TextColor3 = textColor choiceButton.TextXAlignment = Enum.TextXAlignment.Left choiceButton.TextYAlignment = Enum.TextYAlignment.Center choiceButton.BackgroundColor3 = Color3.new(1, 1, 1) choiceButton.Font = Enum.Font.Arial choiceButton.FontSize = Enum.FontSize.Size18 if useScrollButtons then choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0) else choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0) end choiceButton.TextWrap = true choiceButton.ZIndex = 2 + baseZIndex local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = true areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 3 + baseZIndex local dropDownSelected = false local scrollUpButton local scrollDownButton local scrollMouseCount = 0 local setZIndex = function(baseZIndex) droppedDownMenu.ZIndex = baseZIndex +1 if scrollUpButton then scrollUpButton.ZIndex = baseZIndex + 3 end if scrollDownButton then scrollDownButton.ZIndex = baseZIndex + 3 end local children = droppedDownMenu:GetChildren() if children then for i, child in ipairs(children) do if child.Name == "ChoiceButton" then child.ZIndex = baseZIndex + 2 elseif child.Name == "ClickCaptureButton" then child.ZIndex = baseZIndex end end end end local scrollBarPosition = 1 local updateScroll = function() if scrollUpButton then scrollUpButton.Active = scrollBarPosition > 1 end if scrollDownButton then scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount end local children = droppedDownMenu:GetChildren() if not children then return end local childNum = 1 for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then obj.Visible = false else obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0) obj.Visible = true end obj.TextColor3 = textColor obj.BackgroundTransparency = 1 childNum = childNum + 1 end end end local toggleVisibility = function() dropDownSelected = not dropDownSelected areaSoak.Visible = not areaSoak.Visible dropDownMenu.Visible = not dropDownSelected droppedDownMenu.Visible = dropDownSelected if dropDownSelected then setZIndex(4 + baseZIndex) else setZIndex(2 + baseZIndex) end if useScrollButtons then updateScroll() end end droppedDownMenu.MouseButton1Click:connect(toggleVisibility) local updateSelection = function(text) local foundItem = false local children = droppedDownMenu:GetChildren() local childNum = 1 if children then for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if obj.Text == text then obj.Font = Enum.Font.ArialBold foundItem = true scrollBarPosition = childNum if (whiteSkin) then obj.TextColor3 = Color3.new(90/255,142/255,233/255) end else obj.Font = Enum.Font.Arial if (whiteSkin) then obj.TextColor3 = textColor end end childNum = childNum + 1 end end end if not text then dropDownMenu.Text = "Choose One" scrollBarPosition = 1 else if not foundItem then error("Invalid Selection Update -- " .. text) end if scrollBarPosition + dropDownItemCount > itemCount + 1 then scrollBarPosition = itemCount - dropDownItemCount + 1 end dropDownMenu.Text = text end end local function scrollDown() if scrollBarPosition + dropDownItemCount <= itemCount then scrollBarPosition = scrollBarPosition + 1 updateScroll() return true end return false end local function scrollUp() if scrollBarPosition > 1 then scrollBarPosition = scrollBarPosition - 1 updateScroll() return true end return false end if useScrollButtons then --Make some scroll buttons scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0) scrollUpButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollUp() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollUp() == false then break end wait(0.1) end end) scrollUpButton.Parent = droppedDownMenu scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) scrollDownButton.Position = UDim2.new(1,-11,1,-11) scrollDownButton.Parent = droppedDownMenu scrollDownButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollDown() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollDown() == false then break end wait(0.1) end end) local scrollbar = Instance.new("ImageLabel") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4) scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2) scrollbar.Parent = droppedDownMenu end for i,item in ipairs(items) do -- needed to maintain local scope for items in event listeners below local button = choiceButton:clone() if forRoblox then button.RobloxLocked = true end button.Text = item button.Parent = droppedDownMenu if (whiteSkin) then button.TextColor3 = textColor end button.MouseButton1Click:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 updateSelection(item) onSelect(item) toggleVisibility() end) button.MouseEnter:connect(function() --Add Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(0,0,0) end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 end) end --This does the initial layout of the buttons updateScroll() frame.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(frame) end end) dropDownMenu.MouseButton1Click:connect(toggleVisibility) areaSoak.MouseButton1Click:connect(toggleVisibility) return frame, updateSelection end t.CreatePropertyDropDownMenu = function(instance, property, enum) local items = enum:GetEnumItems() local names = {} local nameToItem = {} for i,obj in ipairs(items) do names[i] = obj.Name nameToItem[obj.Name] = obj end local frame local updateSelection frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end) ScopedConnect(frame, instance, "Changed", function(prop) if prop == property then updateSelection(instance[property].Name) end end, function() updateSelection(instance[property].Name) end) return frame end t.GetFontHeight = function(font, fontSize) if font == nil or fontSize == nil then error("Font and FontSize must be non-nil") end if font == Enum.Font.Legacy then if fontSize == Enum.FontSize.Size8 then return 12 elseif fontSize == Enum.FontSize.Size9 then return 14 elseif fontSize == Enum.FontSize.Size10 then return 15 elseif fontSize == Enum.FontSize.Size11 then return 17 elseif fontSize == Enum.FontSize.Size12 then return 18 elseif fontSize == Enum.FontSize.Size14 then return 21 elseif fontSize == Enum.FontSize.Size18 then return 27 elseif fontSize == Enum.FontSize.Size24 then return 36 elseif fontSize == Enum.FontSize.Size36 then return 54 elseif fontSize == Enum.FontSize.Size48 then return 72 else error("Unknown FontSize") end elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then if fontSize == Enum.FontSize.Size8 then return 8 elseif fontSize == Enum.FontSize.Size9 then return 9 elseif fontSize == Enum.FontSize.Size10 then return 10 elseif fontSize == Enum.FontSize.Size11 then return 11 elseif fontSize == Enum.FontSize.Size12 then return 12 elseif fontSize == Enum.FontSize.Size14 then return 14 elseif fontSize == Enum.FontSize.Size18 then return 18 elseif fontSize == Enum.FontSize.Size24 then return 24 elseif fontSize == Enum.FontSize.Size36 then return 36 elseif fontSize == Enum.FontSize.Size48 then return 48 else error("Unknown FontSize") end else error("Unknown Font " .. font) end end local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable) local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y for i, child in ipairs(guiObjects) do if child:IsA("TextLabel") or child:IsA("TextButton") then local isLabel = child:IsA("TextLabel") if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining) if child.TextFits and child.TextBounds.Y < pixelsRemaining then child.Visible = true if isLabel then child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"]) else child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"]) end while not child.TextFits do child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1) end pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end else child.Visible = false pixelsRemaining = -1 end else --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y child.Visible = (pixelsRemaining >= 0) end end end t.LayoutGuiObjects = function(frame, guiObjects, settingsTable) if not frame:IsA("GuiObject") then error("Frame must be a GuiObject") end for i, child in ipairs(guiObjects) do if not child:IsA("GuiObject") then error("All elements that are layed out must be of type GuiObject") end end if not settingsTable then settingsTable = {} end if not settingsTable["TextLabelSizePadY"] then settingsTable["TextLabelSizePadY"] = 0 end if not settingsTable["TextLabelPositionPadY"] then settingsTable["TextLabelPositionPadY"] = 0 end if not settingsTable["TextButtonSizePadY"] then settingsTable["TextButtonSizePadY"] = 12 end if not settingsTable["TextButtonPositionPadY"] then settingsTable["TextButtonPositionPadY"] = 2 end --Wrapper frame takes care of styled objects local wrapperFrame = Instance.new("Frame") wrapperFrame.Name = "WrapperFrame" wrapperFrame.BackgroundTransparency = 1 wrapperFrame.Size = UDim2.new(1,0,1,0) wrapperFrame.Parent = frame for i, child in ipairs(guiObjects) do child.Parent = wrapperFrame end local recalculate = function() wait() layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(recalculate) layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end t.CreateSlider = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 4 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local bar = Instance.new("TextButton") bar.Text = "" bar.AutoButtonColor = false bar.Name = "Bar" bar.BackgroundColor3 = Color3.new(0,0,0) if type(width) == "number" then bar.Size = UDim2.new(0,width,0,5) else bar.Size = UDim2.new(0,200,0,5) end bar.BorderColor3 = Color3.new(95/255,95/255,95/255) bar.ZIndex = 2 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/Slider.png" slider.Position = UDim2.new(0,0,0.5,-10) slider.Size = UDim2.new(0,20,0,20) slider.ZIndex = 3 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (steps - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateSliderNew = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 6 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local sliderBarImgHeight = 7 local sliderBarCapImgWidth = 4 local bar = Instance.new("ImageButton") bar.BackgroundTransparency = 1 bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png" bar.Name = "Bar" local displayWidth = 200 if type(width) == "number" then bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight) displayWidth = width - (sliderBarCapImgWidth * 2) else bar.Size = UDim2.new(0,200,0,sliderBarImgHeight) end bar.ZIndex = 3 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local barLeft = bar:clone() barLeft.Name = "BarLeft" barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png" barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight) barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset) barLeft.Parent = sliderGui barLeft.ZIndex = 3 local barRight = barLeft:clone() barRight.Name = "BarRight" barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png" barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset) barRight.Parent = sliderGui local fillLeft = barLeft:clone() fillLeft.Name = "FillLeft" fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png" fillLeft.Parent = sliderGui fillLeft.ZIndex = 4 local fill = fillLeft:clone() fill.Name = "Fill" fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png" fill.Parent = bar fill.ZIndex = 4 fill.Position = UDim2.new(0, 0, 0, 0) fill.Size = UDim2.new(0.5, 0, 1, 0) -- bar.Visible = false local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/slider_new_tab.png" slider.Position = UDim2.new(0,0,0.5,-14) slider.Size = UDim2.new(0,28,0,28) slider.ZIndex = 5 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (steps - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) fill.Size = UDim2.new(relativePosX, 0, 1, 0) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateTrueScrollingFrame = function() local lowY = nil local highY = nil local dragCon = nil local upCon = nil local internalChange = false local descendantsChangeConMap = {} local scrollingFrame = Instance.new("Frame") scrollingFrame.Name = "ScrollingFrame" scrollingFrame.Active = true scrollingFrame.Size = UDim2.new(1,0,1,0) scrollingFrame.ClipsDescendants = true local controlFrame = Instance.new("Frame") controlFrame.Name = "ControlFrame" controlFrame.BackgroundTransparency = 1 controlFrame.Size = UDim2.new(0,18,1,0) controlFrame.Position = UDim2.new(1,-20,0,0) controlFrame.Parent = scrollingFrame local scrollBottom = Instance.new("BoolValue") scrollBottom.Value = false scrollBottom.Name = "ScrollBottom" scrollBottom.Parent = controlFrame local scrollUp = Instance.new("BoolValue") scrollUp.Value = false scrollUp.Name = "scrollUp" scrollUp.Parent = controlFrame local scrollUpButton = Instance.new("TextButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.Text = "" scrollUpButton.AutoButtonColor = false scrollUpButton.BackgroundColor3 = Color3.new(0,0,0) scrollUpButton.BorderColor3 = Color3.new(1,1,1) scrollUpButton.BackgroundTransparency = 0.5 scrollUpButton.Size = UDim2.new(0,18,0,18) scrollUpButton.ZIndex = 2 scrollUpButton.Parent = controlFrame for i = 1, 6 do local triFrame = Instance.new("Frame") triFrame.BorderColor3 = Color3.new(1,1,1) triFrame.Name = "tri" .. tostring(i) triFrame.ZIndex = 3 triFrame.BackgroundTransparency = 0.5 triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0) triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1)) triFrame.Parent = scrollUpButton end scrollUpButton.MouseEnter:connect(function() scrollUpButton.BackgroundTransparency = 0.1 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.1 end end) scrollUpButton.MouseLeave:connect(function() scrollUpButton.BackgroundTransparency = 0.5 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.5 end end) local scrollDownButton = scrollUpButton:clone() scrollDownButton.Name = "ScrollDownButton" scrollDownButton.Position = UDim2.new(0,0,1,-18) local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1)) end scrollDownButton.MouseEnter:connect(function() scrollDownButton.BackgroundTransparency = 0.1 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.1 end end) scrollDownButton.MouseLeave:connect(function() scrollDownButton.BackgroundTransparency = 0.5 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.5 end end) scrollDownButton.Parent = controlFrame local scrollTrack = Instance.new("Frame") scrollTrack.Name = "ScrollTrack" scrollTrack.BackgroundTransparency = 1 scrollTrack.Size = UDim2.new(0,18,1,-38) scrollTrack.Position = UDim2.new(0,0,0,19) scrollTrack.Parent = controlFrame local scrollbar = Instance.new("TextButton") scrollbar.BackgroundColor3 = Color3.new(0,0,0) scrollbar.BorderColor3 = Color3.new(1,1,1) scrollbar.BackgroundTransparency = 0.5 scrollbar.AutoButtonColor = false scrollbar.Text = "" scrollbar.Active = true scrollbar.Name = "ScrollBar" scrollbar.ZIndex = 2 scrollbar.BackgroundTransparency = 0.5 scrollbar.Size = UDim2.new(0, 18, 0.1, 0) scrollbar.Position = UDim2.new(0,0,0,0) scrollbar.Parent = scrollTrack local scrollNub = Instance.new("Frame") scrollNub.Name = "ScrollNub" scrollNub.BorderColor3 = Color3.new(1,1,1) scrollNub.Size = UDim2.new(0,10,0,0) scrollNub.Position = UDim2.new(0.5,-5,0.5,0) scrollNub.ZIndex = 2 scrollNub.BackgroundTransparency = 0.5 scrollNub.Parent = scrollbar local newNub = scrollNub:clone() newNub.Position = UDim2.new(0.5,-5,0.5,-2) newNub.Parent = scrollbar local lastNub = scrollNub:clone() lastNub.Position = UDim2.new(0.5,-5,0.5,2) lastNub.Parent = scrollbar scrollbar.MouseEnter:connect(function() scrollbar.BackgroundTransparency = 0.1 scrollNub.BackgroundTransparency = 0.1 newNub.BackgroundTransparency = 0.1 lastNub.BackgroundTransparency = 0.1 end) scrollbar.MouseLeave:connect(function() scrollbar.BackgroundTransparency = 0.5 scrollNub.BackgroundTransparency = 0.5 newNub.BackgroundTransparency = 0.5 lastNub.BackgroundTransparency = 0.5 end) local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local function positionScrollBar(x,y,offset) local oldPos = scrollbar.Position if y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) return (oldPos ~= scrollbar.Position) end local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) return (oldPos ~= scrollbar.Position) end local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y if newScaleYPos + relativeSize > 1 then newScaleYPos = 1 - relativeSize scrollBottom.Value = true scrollUp.Value = false elseif newScaleYPos <= 0 then newScaleYPos = 0 scrollUp.Value = true scrollBottom.Value = false else scrollUp.Value = false scrollBottom.Value = false end scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0) return (oldPos ~= scrollbar.Position) end local function drillDownSetHighLow(instance) if not instance or not instance:IsA("GuiObject") then return end if instance == controlFrame then return end if instance:IsDescendantOf(controlFrame) then return end if not instance.Visible then return end if lowY and lowY > instance.AbsolutePosition.Y then lowY = instance.AbsolutePosition.Y elseif not lowY then lowY = instance.AbsolutePosition.Y end if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end local children = instance:GetChildren() for i = 1, #children do drillDownSetHighLow(children[i]) end end local function resetHighLow() local firstChildren = scrollingFrame:GetChildren() for i = 1, #firstChildren do drillDownSetHighLow(firstChildren[i]) end end local function recalculate() internalChange = true local percentFrame = 0 if scrollbar.Position.Y.Scale > 0 then if scrollbar.Visible then percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y) else percentFrame = 0 end end if percentFrame > 0.99 then percentFrame = 1 end local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame local guiChildren = scrollingFrame:GetChildren() for i = 1, #guiChildren do if guiChildren[i] ~= controlFrame then guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset, 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount) end end lowY = nil highY = nil resetHighLow() internalChange = false end local function setSliderSizeAndPosition() if not highY or not lowY then return end local totalYSpan = math.abs(highY - lowY) if totalYSpan == 0 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end return end local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan if percentShown >= 1 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false recalculate() else scrollbar.Visible = true scrollDownButton.Visible = true scrollUpButton.Visible = true scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0) end local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2) if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) end if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) end end local buttonScrollAmountPixels = 7 local reentrancyGuardScrollUp = false local function doScrollUp() if reentrancyGuardScrollUp then return end reentrancyGuardScrollUp = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollUp = false end local reentrancyGuardScrollDown = false local function doScrollDown() if reentrancyGuardScrollDown then return end reentrancyGuardScrollDown = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollDown = false end local function scrollUp(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local function scrollDown(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end scrollbar.MouseButton1Down:connect(function(x,y) if scrollbar.Active then scrollStamp = tick() local mouseOffset = y - scrollbar.AbsolutePosition.y if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end local prevY = y local reentrancyGuardMouseScroll = false dragCon = mouseDrag.MouseMoved:connect(function(x,y) if reentrancyGuardMouseScroll then return end reentrancyGuardMouseScroll = true if positionScrollBar(x,y,mouseOffset) then recalculate() end reentrancyGuardMouseScroll = false end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect(function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect(function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) local function heightCheck(instance) if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end setSliderSizeAndPosition() end local function highLowRecheck() local oldLowY = lowY local oldHighY = highY lowY = nil highY = nil resetHighLow() if (lowY ~= oldLowY) or (highY ~= oldHighY) then setSliderSizeAndPosition() end end local function descendantChanged(this, prop) if internalChange then return end if not this.Visible then return end if prop == "Size" or prop == "Position" then wait() highLowRecheck() end end scrollingFrame.DescendantAdded:connect(function(instance) if not instance:IsA("GuiObject") then return end if instance.Visible then wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end) end) scrollingFrame.DescendantRemoving:connect(function(instance) if not instance:IsA("GuiObject") then return end if descendantsChangeConMap[instance] then descendantsChangeConMap[instance]:disconnect() descendantsChangeConMap[instance] = nil end wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end) scrollingFrame.Changed:connect(function(prop) if prop == "AbsoluteSize" then if not highY or not lowY then return end highLowRecheck() setSliderSizeAndPosition() end end) return scrollingFrame, controlFrame end t.CreateScrollingFrame = function(orderList,scrollStyle) local frame = Instance.new("Frame") frame.Name = "ScrollingFrame" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1,0,1,0) local scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) local scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) local scrollbar = Instance.new("ImageButton") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, 0, 150) local scrollStamp = 0 local scrollDrag = Instance.new("ImageButton") scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186" scrollDrag.Size = UDim2.new(1, 0, 0, 16) scrollDrag.BackgroundTransparency = 1 scrollDrag.Name = "ScrollDrag" scrollDrag.Active = true scrollDrag.Parent = scrollbar local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local style = "simple" if scrollStyle and tostring(scrollStyle) then style = scrollStyle end local scrollPosition = 1 local rowSize = 0 local howManyDisplayed = 0 local layoutGridScrollBar = function() howManyDisplayed = 0 local guiObjects = {} if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end if scrollPosition < 1 then scrollPosition = 1 end local totalPixelsY = frame.AbsoluteSize.Y local pixelsRemainingY = frame.AbsoluteSize.Y local totalPixelsX = frame.AbsoluteSize.X local xCounter = 0 local rowSizeCounter = 0 local setRowSize = true local pixelsBelowScrollbar = 0 local pos = #guiObjects local currentRowY = 0 pos = scrollPosition --count up from current scroll position to fill out grid while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X --previous pos was the end of a row if xCounter >= totalPixelsX then pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 xCounter = guiObjects[pos].AbsoluteSize.X end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos + 1 end --Count wherever current row left off pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 pos = scrollPosition - 1 xCounter = 0 --objects with varying X,Y dimensions can rarely cause minor errors --rechecking every new scrollPosition is necessary to avoid 100% of errors --count backwards from current scrollPosition to see if we can add more rows while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X rowSizeCounter = rowSizeCounter + 1 if xCounter >= totalPixelsX then rowSize = rowSizeCounter - 1 rowSizeCounter = 0 xCounter = guiObjects[pos].AbsoluteSize.X if pixelsBelowScrollbar + currentRowY <= totalPixelsY then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY if scrollPosition <= rowSize then scrollPosition = 1 break else scrollPosition = scrollPosition - rowSize end currentRowY = 0 else break end end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos - 1 end --Do check last time if pos = 0 if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then scrollPosition = 1 end xCounter = 0 --pos = scrollPosition rowSizeCounter = 0 setRowSize = true local lastChildSize = 0 local xOffset,yOffset = 0 if guiObjects[1] then yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2) xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2) end for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemainingY < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject if setRowSize then rowSizeCounter = rowSizeCounter + 1 end if xCounter + child.AbsoluteSize.X >= totalPixelsX then if setRowSize then rowSize = rowSizeCounter - 1 setRowSize = false end xCounter = 0 pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y end child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset) xCounter = xCounter + child.AbsoluteSize.X child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0) if child.Visible then howManyDisplayed = howManyDisplayed + 1 end lastChildSize = child.AbsoluteSize end end end scrollUpButton.Active = (scrollPosition > 1) if lastChildSize == 0 then scrollDownButton.Active = false else scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0) end scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local layoutSimpleScrollBar = function() local guiObjects = {} howManyDisplayed = 0 if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y local pixelsBelowScrollbar = 0 local pos = #guiObjects while pixelsBelowScrollbar < totalPixels and pos >= 1 do if pos >= scrollPosition then pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y else if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y if scrollPosition <= 1 then scrollPosition = 1 break else --local ("Backing up ScrollPosition from -- " ..scrollPosition) scrollPosition = scrollPosition - 1 end else break end end pos = pos - 1 end pos = scrollPosition for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemaining < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if (pixelsRemaining >= 0) then child.Visible = true howManyDisplayed = howManyDisplayed + 1 else child.Visible = false end end end end scrollUpButton.Active = (scrollPosition > 1) scrollDownButton.Active = (pixelsRemaining < 0) scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local moveDragger = function() local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end if not scrollDrag.Parent then return end local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1)) if dragSizeY < 16 then dragSizeY = 16 end scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY) local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed)) if relativeYPos > 1 then relativeYPos = 1 elseif relativeYPos < 0 then relativeYPos = 0 end local absYPos = 0 if relativeYPos ~= 0 then absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y) end scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos) end local reentrancyGuard = false local recalculate = function() if reentrancyGuard then return end reentrancyGuard = true wait() local success, err = nil if style == "grid" then success, err = pcall(function() layoutGridScrollBar() end) elseif style == "simple" then success, err = pcall(function() layoutSimpleScrollBar() end) end if not success then print(err) end moveDragger() reentrancyGuard = false end local doScrollUp = function() scrollPosition = (scrollPosition) - rowSize if scrollPosition < 1 then scrollPosition = 1 end recalculate(nil) end local doScrollDown = function() scrollPosition = (scrollPosition) + rowSize recalculate(nil) end local scrollUp = function(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local scrollDown = function(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local y = 0 scrollDrag.MouseButton1Down:connect(function(x,y) if scrollDrag.Active then scrollStamp = tick() local mouseOffset = y - scrollDrag.AbsolutePosition.y local dragCon local upCon dragCon = mouseDrag.MouseMoved:connect(function(x,y) local barAbsPos = scrollbar.AbsolutePosition.y local barAbsSize = scrollbar.AbsoluteSize.y local dragAbsSize = scrollDrag.AbsoluteSize.y local barAbsOne = barAbsPos + barAbsSize - dragAbsSize y = y - mouseOffset y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y y = y - barAbsPos local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end local doublePercent = y/(barAbsSize-dragAbsSize) local rowDiff = rowSize local totalScrollCount = guiObjects - (howManyDisplayed - 1) local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff if newScrollPosition < scrollPosition then rowDiff = -rowDiff end if newScrollPosition < 1 then newScrollPosition = 1 end scrollPosition = newScrollPosition recalculate(nil) end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect( function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect( function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollbar.MouseButton1Down:connect( function(x,y) if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then scrollDown(y) elseif y < (scrollDrag.AbsolutePosition.y) then scrollUp(y) end end) frame.ChildAdded:connect(function() recalculate(nil) end) frame.ChildRemoved:connect(function() recalculate(nil) end) frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(function() recalculate(nil) end) return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar end local function binaryGrow(min, max, fits) if min > max then return min end local biggestLegal = min while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then biggestLegal = mid --Try growing min = mid + 1 else --Doesn't fit, shrink max = mid - 1 end end return biggestLegal end local function binaryShrink(min, max, fits) if min > max then return min end local smallestLegal = max while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then smallestLegal = mid --It fits, shrink max = mid - 1 else --Doesn't fit, grow min = mid + 1 end end return smallestLegal end local function getGuiOwner(instance) while instance ~= nil do if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then return instance end instance = instance.Parent end return nil end t.AutoTruncateTextObject = function(textLabel) local text = textLabel.Text local fullLabel = textLabel:Clone() fullLabel.Name = "Full" .. textLabel.Name fullLabel.BorderSizePixel = 0 fullLabel.BackgroundTransparency = 0 fullLabel.Text = text fullLabel.TextXAlignment = Enum.TextXAlignment.Center fullLabel.Position = UDim2.new(0,-3,0,0) fullLabel.Size = UDim2.new(0,100,1,0) fullLabel.Visible = false fullLabel.Parent = textLabel local shortText = nil local mouseEnterConnection = nil local mouseLeaveConnection= nil local checkForResize = function() if getGuiOwner(textLabel) == nil then return end textLabel.Text = text if textLabel.TextFits then --Tear down the rollover if it is active if mouseEnterConnection then mouseEnterConnection:disconnect() mouseEnterConnection = nil end if mouseLeaveConnection then mouseLeaveConnection:disconnect() mouseLeaveConnection = nil end else local len = string.len(text) textLabel.Text = text .. "~" --Shrink the text local textSize = binaryGrow(0, len, function(pos) if pos == 0 then textLabel.Text = "~" else textLabel.Text = string.sub(text, 1, pos) .. "~" end return textLabel.TextFits end) shortText = string.sub(text, 1, textSize) .. "~" textLabel.Text = shortText --Make sure the fullLabel fits if not fullLabel.TextFits then --Already too small, grow it really bit to start fullLabel.Size = UDim2.new(0, 10000, 1, 0) end --Okay, now try to binary shrink it back down local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X, function(size) fullLabel.Size = UDim2.new(0, size, 1, 0) return fullLabel.TextFits end) fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0) --Now setup the rollover effects, if they are currently off if mouseEnterConnection == nil then mouseEnterConnection = textLabel.MouseEnter:connect( function() fullLabel.ZIndex = textLabel.ZIndex + 1 fullLabel.Visible = true --textLabel.Text = "" end) end if mouseLeaveConnection == nil then mouseLeaveConnection = textLabel.MouseLeave:connect( function() fullLabel.Visible = false --textLabel.Text = shortText end) end end end textLabel.AncestryChanged:connect(checkForResize) textLabel.Changed:connect( function(prop) if prop == "AbsoluteSize" then checkForResize() end end) checkForResize() local function changeText(newText) text = newText fullLabel.Text = text checkForResize() end return textLabel, changeText end local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue) if fromPage then fromPage.Visible = false if transitionFrame.Visible == false then transitionFrame.Size = fromPage.Size transitionFrame.Position = fromPage.Position end else if transitionFrame.Visible == false then transitionFrame.Size = UDim2.new(0.0,50,0.0,50) transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25) end end transitionFrame.Visible = true currentPageValue.Value = nil local newsize, newPosition if toPage then --Make it visible so it resizes toPage.Visible = true newSize = toPage.Size newPosition = toPage.Position toPage.Visible = false else newSize = UDim2.new(0.0,50,0.0,50) newPosition = UDim2.new(0.5,-25,0.5,-25) end transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true, function(state) if state == Enum.TweenStatus.Completed then transitionFrame.Visible = false if toPage then toPage.Visible = true currentPageValue.Value = toPage end end end) end t.CreateTutorial = function(name, tutorialKey, createButtons) local frame = Instance.new("Frame") frame.Name = "Tutorial-" .. name frame.BackgroundTransparency = 1 frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) local transitionFrame = Instance.new("Frame") transitionFrame.Name = "TransitionFrame" transitionFrame.Style = Enum.FrameStyle.RobloxRound transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0) transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0) transitionFrame.Visible = false transitionFrame.Parent = frame local currentPageValue = Instance.new("ObjectValue") currentPageValue.Name = "CurrentTutorialPage" currentPageValue.Value = nil currentPageValue.Parent = frame local boolValue = Instance.new("BoolValue") boolValue.Name = "Buttons" boolValue.Value = createButtons boolValue.Parent = frame local pages = Instance.new("Frame") pages.Name = "Pages" pages.BackgroundTransparency = 1 pages.Size = UDim2.new(1,0,1,0) pages.Parent = frame local function getVisiblePageAndHideOthers() local visiblePage = nil local children = pages:GetChildren() if children then for i,child in ipairs(children) do if child.Visible then if visiblePage then child.Visible = false else visiblePage = child end end end end return visiblePage end local showTutorial = function(alwaysShow) if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then print("Showing tutorial-",tutorialKey) local currentTutorialPage = getVisiblePageAndHideOthers() local firstPage = pages:FindFirstChild("TutorialPage1") if firstPage then TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue) else error("Could not find TutorialPage1") end end end local dismissTutorial = function() local currentTutorialPage = getVisiblePageAndHideOthers() if currentTutorialPage then TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue) end UserSettings().GameSettings:SetTutorialState(tutorialKey, true) end local gotoPage = function(pageNum) local page = pages:FindFirstChild("TutorialPage" .. pageNum) local currentTutorialPage = getVisiblePageAndHideOthers() TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue) end return frame, showTutorial, dismissTutorial, gotoPage end local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton) local frame = Instance.new("Frame") frame.Name = "TutorialPage" frame.Style = Enum.FrameStyle.RobloxRound frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) frame.Visible = false local frameHeader = Instance.new("TextLabel") frameHeader.Name = "Header" frameHeader.Text = name frameHeader.BackgroundTransparency = 1 frameHeader.FontSize = Enum.FontSize.Size24 frameHeader.Font = Enum.Font.ArialBold frameHeader.TextColor3 = Color3.new(1,1,1) frameHeader.TextXAlignment = Enum.TextXAlignment.Center frameHeader.TextWrap = true frameHeader.Size = UDim2.new(1,-55, 0, 22) frameHeader.Position = UDim2.new(0,0,0,0) frameHeader.Parent = frame local skipButton = Instance.new("ImageButton") skipButton.Name = "SkipButton" skipButton.AutoButtonColor = false skipButton.BackgroundTransparency = 1 skipButton.Image = "rbxasset://textures/ui/closeButton.png" skipButton.MouseButton1Click:connect(function() skipTutorial() end) skipButton.MouseEnter:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png" end) skipButton.MouseLeave:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton.png" end) skipButton.Size = UDim2.new(0, 25, 0, 25) skipButton.Position = UDim2.new(1, -25, 0, 0) skipButton.Parent = frame if giveDoneButton then local doneButton = Instance.new("TextButton") doneButton.Name = "DoneButton" doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault doneButton.Text = "Done" doneButton.TextColor3 = Color3.new(1,1,1) doneButton.Font = Enum.Font.ArialBold doneButton.FontSize = Enum.FontSize.Size18 doneButton.Size = UDim2.new(0,100,0,50) doneButton.Position = UDim2.new(0.5,-50,1,-50) if skipTutorial then doneButton.MouseButton1Click:connect(function() skipTutorial() end) end doneButton.Parent = frame end local innerFrame = Instance.new("Frame") innerFrame.Name = "ContentFrame" innerFrame.BackgroundTransparency = 1 innerFrame.Position = UDim2.new(0,0,0,25) innerFrame.Parent = frame local nextButton = Instance.new("TextButton") nextButton.Name = "NextButton" nextButton.Text = "Next" nextButton.TextColor3 = Color3.new(1,1,1) nextButton.Font = Enum.Font.Arial nextButton.FontSize = Enum.FontSize.Size18 nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault nextButton.Size = UDim2.new(0,80, 0, 32) nextButton.Position = UDim2.new(0.5, 5, 1, -32) nextButton.Active = false nextButton.Visible = false nextButton.Parent = frame local prevButton = Instance.new("TextButton") prevButton.Name = "PrevButton" prevButton.Text = "Previous" prevButton.TextColor3 = Color3.new(1,1,1) prevButton.Font = Enum.Font.Arial prevButton.FontSize = Enum.FontSize.Size18 prevButton.Style = Enum.ButtonStyle.RobloxButton prevButton.Size = UDim2.new(0,80, 0, 32) prevButton.Position = UDim2.new(0.5, -85, 1, -32) prevButton.Active = false prevButton.Visible = false prevButton.Parent = frame if giveDoneButton then innerFrame.Size = UDim2.new(1,0,1,-75) else innerFrame.Size = UDim2.new(1,0,1,-22) end local parentConnection = nil local function basicHandleResize() if frame.Visible and frame.Parent then local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y) handleResize(200,maxSize) end end frame.Changed:connect( function(prop) if prop == "Parent" then if parentConnection ~= nil then parentConnection:disconnect() parentConnection = nil end if frame.Parent and frame.Parent:IsA("GuiObject") then parentConnection = frame.Parent.Changed:connect( function(parentProp) if parentProp == "AbsoluteSize" then wait() basicHandleResize() end end) basicHandleResize() end end if prop == "Visible" then basicHandleResize() end end) return frame, innerFrame end t.CreateTextTutorialPage = function(name, text, skipTutorialFunc) local frame = nil local contentFrame = nil local textLabel = Instance.new("TextLabel") textLabel.BackgroundTransparency = 1 textLabel.TextColor3 = Color3.new(1,1,1) textLabel.Text = text textLabel.TextWrap = true textLabel.TextXAlignment = Enum.TextXAlignment.Left textLabel.TextYAlignment = Enum.TextYAlignment.Center textLabel.Font = Enum.Font.Arial textLabel.FontSize = Enum.FontSize.Size14 textLabel.Size = UDim2.new(1,0,1,0) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) frame.Size = UDim2.new(0, size, 0, size) return textLabel.TextFits end) frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc) textLabel.Parent = contentFrame return frame end t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton) local frame = nil local contentFrame = nil local imageLabel = Instance.new("ImageLabel") imageLabel.BackgroundTransparency = 1 imageLabel.Image = imageAsset imageLabel.Size = UDim2.new(0,x,0,y) imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) return size >= x and size >= y end) if size >= x and size >= y then imageLabel.Size = UDim2.new(0,x, 0,y) imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2) else if x > y then --X is limiter, so imageLabel.Size = UDim2.new(1,0,y/x,0) imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0) else --Y is limiter imageLabel.Size = UDim2.new(x/y,0,1, 0) imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0) end end size = size + 50 frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton) imageLabel.Parent = contentFrame return frame end t.AddTutorialPage = function(tutorial, tutorialPage) local transitionFrame = tutorial.TransitionFrame local currentPageValue = tutorial.CurrentTutorialPage if not tutorial.Buttons.Value then tutorialPage.NextButton.Parent = nil tutorialPage.PrevButton.Parent = nil end local children = tutorial.Pages:GetChildren() if children and #children > 0 then tutorialPage.Name = "TutorialPage" .. (#children+1) local previousPage = children[#children] if not previousPage:IsA("GuiObject") then error("All elements under Pages must be GuiObjects") end if tutorial.Buttons.Value then if previousPage.NextButton.Active then error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function") end previousPage.NextButton.MouseButton1Click:connect( function() TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue) end) previousPage.NextButton.Active = true previousPage.NextButton.Visible = true if tutorialPage.PrevButton.Active then error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function") end tutorialPage.PrevButton.MouseButton1Click:connect( function() TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue) end) tutorialPage.PrevButton.Active = true tutorialPage.PrevButton.Visible = true end tutorialPage.Parent = tutorial.Pages else --First child tutorialPage.Name = "TutorialPage1" tutorialPage.Parent = tutorial.Pages end end t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId) if not userIdsForSets then error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids") end if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata") end if not objectSelected then error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!") end if type(objectSelected) ~= "function" then error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!") end if dialogClosed and type(dialogClosed) ~= "function" then error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!") end if showAdminCategories == nil then -- by default, don't show beta sets showAdminCategories = false end local arrayPosition = 1 local insertButtons = {} local insertButtonCons = {} local contents = nil local setGui = nil -- used for water selections local waterForceDirection = "NegX" local waterForce = "None" local waterGui, waterTypeChangedEvent = nil local Data = {} Data.CurrentCategory = nil Data.Category = {} local SetCache = {} local userCategoryButtons = nil local buttonWidth = 64 local buttonHeight = buttonWidth local SmallThumbnailUrl = nil local LargeThumbnailUrl = nil local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower() if useAssetVersionId then LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid=" else LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid=" end local function drillDownSetZIndex(parent, index) local children = parent:GetChildren() for i = 1, #children do if children[i]:IsA("GuiObject") then children[i].ZIndex = index end drillDownSetZIndex(children[i], index) end end -- for terrain stamping local currTerrainDropDownFrame = nil local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"} local terrainShapeMap = {} for i = 1, #terrainShapes do terrainShapeMap[terrainShapes[i]] = i - 1 end terrainShapeMap[terrainShapes[#terrainShapes]] = 6 local function createWaterGui() local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"} local waterForces = {"None", "Small", "Medium", "Strong", "Max"} local waterFrame = Instance.new("Frame") waterFrame.Name = "WaterFrame" waterFrame.Style = Enum.FrameStyle.RobloxSquare waterFrame.Size = UDim2.new(0,150,0,110) waterFrame.Visible = false local waterForceLabel = Instance.new("TextLabel") waterForceLabel.Name = "WaterForceLabel" waterForceLabel.BackgroundTransparency = 1 waterForceLabel.Size = UDim2.new(1,0,0,12) waterForceLabel.Font = Enum.Font.ArialBold waterForceLabel.FontSize = Enum.FontSize.Size12 waterForceLabel.TextColor3 = Color3.new(1,1,1) waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left waterForceLabel.Text = "Water Force" waterForceLabel.Parent = waterFrame local waterForceDirLabel = waterForceLabel:Clone() waterForceDirLabel.Name = "WaterForceDirectionLabel" waterForceDirLabel.Text = "Water Force Direction" waterForceDirLabel.Position = UDim2.new(0,0,0,50) waterForceDirLabel.Parent = waterFrame local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame) waterTypeChangedEvent.Name = "WaterTypeChangedEvent" local waterForceDirectionSelectedFunc = function(newForceDirection) waterForceDirection = newForceDirection waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceSelectedFunc = function(newForce) waterForce = newForce waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc) waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25) waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3) forceWaterDirectionSelection("NegX") waterForceDirectionDropDown.Parent = waterForceDirLabel local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc) forceWaterForceSelection("None") waterForceDropDown.Size = UDim2.new(1,0,0,25) waterForceDropDown.Position = UDim2.new(0,0,1,3) waterForceDropDown.Parent = waterForceLabel return waterFrame, waterTypeChangedEvent end -- Helper Function that contructs gui elements local function createSetGui() local setGui = Instance.new("ScreenGui") setGui.Name = "SetGui" local setPanel = Instance.new("Frame") setPanel.Name = "SetPanel" setPanel.Active = true setPanel.BackgroundTransparency = 1 if position then setPanel.Position = position else setPanel.Position = UDim2.new(0.2, 29, 0.1, 24) end if size then setPanel.Size = size else setPanel.Size = UDim2.new(0.6, -58, 0.64, 0) end setPanel.Style = Enum.FrameStyle.RobloxRound setPanel.ZIndex = 6 setPanel.Parent = setGui -- Children of SetPanel local itemPreview = Instance.new("Frame") itemPreview.Name = "ItemPreview" itemPreview.BackgroundTransparency = 1 itemPreview.Position = UDim2.new(0.8,5,0.085,0) itemPreview.Size = UDim2.new(0.21,0,0.9,0) itemPreview.ZIndex = 6 itemPreview.Parent = setPanel -- Children of ItemPreview local textPanel = Instance.new("Frame") textPanel.Name = "TextPanel" textPanel.BackgroundTransparency = 1 textPanel.Position = UDim2.new(0,0,0.45,0) textPanel.Size = UDim2.new(1,0,0.55,0) textPanel.ZIndex = 6 textPanel.Parent = itemPreview -- Children of TextPanel local rolloverText = Instance.new("TextLabel") rolloverText.Name = "RolloverText" rolloverText.BackgroundTransparency = 1 rolloverText.Size = UDim2.new(1,0,0,48) rolloverText.ZIndex = 6 rolloverText.Font = Enum.Font.ArialBold rolloverText.FontSize = Enum.FontSize.Size24 rolloverText.Text = "" rolloverText.TextColor3 = Color3.new(1,1,1) rolloverText.TextWrap = true rolloverText.TextXAlignment = Enum.TextXAlignment.Left rolloverText.TextYAlignment = Enum.TextYAlignment.Top rolloverText.Parent = textPanel local largePreview = Instance.new("ImageLabel") largePreview.Name = "LargePreview" largePreview.BackgroundTransparency = 1 largePreview.Image = "" largePreview.Size = UDim2.new(1,0,0,170) largePreview.ZIndex = 6 largePreview.Parent = itemPreview local sets = Instance.new("Frame") sets.Name = "Sets" sets.BackgroundTransparency = 1 sets.Position = UDim2.new(0,0,0,5) sets.Size = UDim2.new(0.23,0,1,-5) sets.ZIndex = 6 sets.Parent = setPanel -- Children of Sets local line = Instance.new("Frame") line.Name = "Line" line.BackgroundColor3 = Color3.new(1,1,1) line.BackgroundTransparency = 0.7 line.BorderSizePixel = 0 line.Position = UDim2.new(1,-3,0.06,0) line.Size = UDim2.new(0,3,0.9,0) line.ZIndex = 6 line.Parent = sets local setsLists, controlFrame = t.CreateTrueScrollingFrame() setsLists.Size = UDim2.new(1,-6,0.94,0) setsLists.Position = UDim2.new(0,0,0.06,0) setsLists.BackgroundTransparency = 1 setsLists.Name = "SetsLists" setsLists.ZIndex = 6 setsLists.Parent = sets drillDownSetZIndex(controlFrame, 7) local setsHeader = Instance.new("TextLabel") setsHeader.Name = "SetsHeader" setsHeader.BackgroundTransparency = 1 setsHeader.Size = UDim2.new(0,47,0,24) setsHeader.ZIndex = 6 setsHeader.Font = Enum.Font.ArialBold setsHeader.FontSize = Enum.FontSize.Size24 setsHeader.Text = "Sets" setsHeader.TextColor3 = Color3.new(1,1,1) setsHeader.TextXAlignment = Enum.TextXAlignment.Left setsHeader.TextYAlignment = Enum.TextYAlignment.Top setsHeader.Parent = sets local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(1,-32,0,-2) cancelButton.Size = UDim2.new(0,34,0,34) cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault cancelButton.ZIndex = 6 cancelButton.Text = "" cancelButton.Modal = true cancelButton.Parent = setPanel -- Children of Cancel Button local cancelImage = Instance.new("ImageLabel") cancelImage.Name = "CancelImage" cancelImage.BackgroundTransparency = 1 cancelImage.Image = "http://www.roblox.com/asset/?id=54135717" cancelImage.Position = UDim2.new(0,-2,0,-2) cancelImage.Size = UDim2.new(0,16,0,16) cancelImage.ZIndex = 6 cancelImage.Parent = cancelButton return setGui end local function createSetButton(text) local setButton = Instance.new("TextButton") if text then setButton.Text = text else setButton.Text = "" end setButton.AutoButtonColor = false setButton.BackgroundTransparency = 1 setButton.BackgroundColor3 = Color3.new(1,1,1) setButton.BorderSizePixel = 0 setButton.Size = UDim2.new(1,-5,0,18) setButton.ZIndex = 6 setButton.Visible = false setButton.Font = Enum.Font.Arial setButton.FontSize = Enum.FontSize.Size18 setButton.TextColor3 = Color3.new(1,1,1) setButton.TextXAlignment = Enum.TextXAlignment.Left return setButton end local function buildSetButton(name, setId, setImageId, i, count) local button = createSetButton(name) button.Text = name button.Name = "SetButton" button.Visible = true local setValue = Instance.new("IntValue") setValue.Name = "SetId" setValue.Value = setId setValue.Parent = button local setName = Instance.new("StringValue") setName.Name = "SetName" setName.Value = name setName.Parent = button return button end local function processCategory(sets) local setButtons = {} local numSkipped = 0 for i = 1, #sets do if not showAdminCategories and sets[i].Name == "Beta" then numSkipped = numSkipped + 1 else setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets) end end return setButtons end local function handleResize() wait() -- neccessary to insure heartbeat happened local itemPreview = setGui.SetPanel.ItemPreview itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X) itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0) itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y) itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y) end local function makeInsertAssetButton() local insertAssetButtonExample = Instance.new("Frame") insertAssetButtonExample.Name = "InsertAssetButtonExample" insertAssetButtonExample.Position = UDim2.new(0,128,0,64) insertAssetButtonExample.Size = UDim2.new(0,64,0,64) insertAssetButtonExample.BackgroundTransparency = 1 insertAssetButtonExample.ZIndex = 6 insertAssetButtonExample.Visible = false local assetId = Instance.new("IntValue") assetId.Name = "AssetId" assetId.Value = 0 assetId.Parent = insertAssetButtonExample local assetName = Instance.new("StringValue") assetName.Name = "AssetName" assetName.Value = "" assetName.Parent = insertAssetButtonExample local button = Instance.new("TextButton") button.Name = "Button" button.Text = "" button.Style = Enum.ButtonStyle.RobloxButton button.Position = UDim2.new(0.025,0,0.025,0) button.Size = UDim2.new(0.95,0,0.95,0) button.ZIndex = 6 button.Parent = insertAssetButtonExample local buttonImage = Instance.new("ImageLabel") buttonImage.Name = "ButtonImage" buttonImage.Image = "" buttonImage.Position = UDim2.new(0,-7,0,-7) buttonImage.Size = UDim2.new(1,14,1,14) buttonImage.BackgroundTransparency = 1 buttonImage.ZIndex = 7 buttonImage.Parent = button local configIcon = buttonImage:clone() configIcon.Name = "ConfigIcon" configIcon.Visible = false configIcon.Position = UDim2.new(1,-23,1,-24) configIcon.Size = UDim2.new(0,16,0,16) configIcon.Image = "" configIcon.ZIndex = 6 configIcon.Parent = insertAssetButtonExample return insertAssetButtonExample end local function showLargePreview(insertButton) if insertButton:FindFirstChild("AssetId") then delay(0,function() game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)) setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value) end) end if insertButton:FindFirstChild("AssetName") then setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value end end local function selectTerrainShape(shape) if currTerrainDropDownFrame then objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape) end end local function createTerrainTypeButton(name, parent) local dropDownTextButton = Instance.new("TextButton") dropDownTextButton.Name = name .. "Button" dropDownTextButton.Font = Enum.Font.ArialBold dropDownTextButton.FontSize = Enum.FontSize.Size14 dropDownTextButton.BorderSizePixel = 0 dropDownTextButton.TextColor3 = Color3.new(1,1,1) dropDownTextButton.Text = name dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.ZIndex = parent.ZIndex + 1 dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16) dropDownTextButton.Position = UDim2.new(0,1,0,0) dropDownTextButton.MouseEnter:connect(function() dropDownTextButton.BackgroundTransparency = 0 dropDownTextButton.TextColor3 = Color3.new(0,0,0) end) dropDownTextButton.MouseLeave:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) end) dropDownTextButton.MouseButton1Click:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then dropDownTextButton.Parent.Visible = false end selectTerrainShape(terrainShapeMap[dropDownTextButton.Text]) end) return dropDownTextButton end local function createTerrainDropDownMenu(zIndex) local dropDown = Instance.new("Frame") dropDown.Name = "TerrainDropDown" dropDown.BackgroundColor3 = Color3.new(0,0,0) dropDown.BorderColor3 = Color3.new(1,0,0) dropDown.Size = UDim2.new(0,200,0,0) dropDown.Visible = false dropDown.ZIndex = zIndex dropDown.Parent = setGui for i = 1, #terrainShapes do local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown) shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset)) shapeButton.Parent = dropDown dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset)) end dropDown.MouseLeave:connect(function() dropDown.Visible = false end) end local function createDropDownMenuButton(parent) local dropDownButton = Instance.new("ImageButton") dropDownButton.Name = "DropDownButton" dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509" dropDownButton.BackgroundTransparency = 1 dropDownButton.Size = UDim2.new(0,16,0,16) dropDownButton.Position = UDim2.new(1,-24,0,6) dropDownButton.ZIndex = parent.ZIndex + 2 dropDownButton.Parent = parent if not setGui:FindFirstChild("TerrainDropDown") then createTerrainDropDownMenu(8) end dropDownButton.MouseButton1Click:connect(function() setGui.TerrainDropDown.Visible = true setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y) currTerrainDropDownFrame = parent end) end local function buildInsertButton() local insertButton = makeInsertAssetButton() insertButton.Name = "InsertAssetButton" insertButton.Visible = true if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then createDropDownMenuButton(insertButton) end local lastEnter = nil local mouseEnterCon = insertButton.MouseEnter:connect(function() lastEnter = insertButton delay(0.1,function() if lastEnter == insertButton then showLargePreview(insertButton) end end) end) return insertButton, mouseEnterCon end local function realignButtonGrid(columns) local x = 0 local y = 0 for i = 1, #insertButtons do insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y) x = x + 1 if x >= columns then x = 0 y = y + 1 end end end local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId) if visible then insertFrame.AssetName.Value = name insertFrame.AssetId.Value = assetId local newImageUrl = SmallThumbnailUrl .. assetId if newImageUrl ~= insertFrame.Button.ButtonImage.Image then delay(0,function() game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId) if insertFrame:findFirstChild("Button") then insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId end end) end table.insert(insertButtonCons, insertFrame.Button.MouseButton1Click:connect(function() -- special case for water, show water selection gui local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability") waterGui.Visible = isWaterSelected if isWaterSelected then objectSelected(name, tonumber(assetId), nil) else objectSelected(name, tonumber(assetId)) end end) ) insertFrame.Visible = true else insertFrame.Visible = false end end local function loadSectionOfItems(setGui, rows, columns) local pageSize = rows * columns if arrayPosition > #contents then return end local origArrayPos = arrayPosition local yCopy = 0 for i = 1, pageSize + 1 do if arrayPosition >= #contents + 1 then break end local buttonCon insertButtons[arrayPosition], buttonCon = buildInsertButton() table.insert(insertButtonCons,buttonCon) insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame arrayPosition = arrayPosition + 1 end realignButtonGrid(columns) local indexCopy = origArrayPos for index = origArrayPos, arrayPosition do if insertButtons[index] then if contents[index] then -- we don't want water to have a drop down button if contents[index].Name == "Water" then if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy() end end local assetId if useAssetVersionId then assetId = contents[index].AssetVersionId else assetId = contents[index].AssetId end setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId) else break end else break end indexCopy = index end end local function setSetIndex() Data.Category[Data.CurrentCategory].Index = 0 rows = 7 columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) contents = Data.Category[Data.CurrentCategory].Contents if contents then -- remove our buttons and their connections for i = 1, #insertButtons do insertButtons[i]:remove() end for i = 1, #insertButtonCons do if insertButtonCons[i] then insertButtonCons[i]:disconnect() end end insertButtonCons = {} insertButtons = {} arrayPosition = 1 loadSectionOfItems(setGui, rows, columns) end end local function selectSet(button, setName, setId, setIndex) if button and Data.Category[Data.CurrentCategory] ~= nil then if button ~= Data.Category[Data.CurrentCategory].Button then Data.Category[Data.CurrentCategory].Button = button if SetCache[setId] == nil then SetCache[setId] = game:GetService("InsertService"):GetCollection(setId) end Data.Category[Data.CurrentCategory].Contents = SetCache[setId] Data.Category[Data.CurrentCategory].SetName = setName Data.Category[Data.CurrentCategory].SetId = setId end setSetIndex() end end local function selectCategoryPage(buttons, page) if buttons ~= Data.CurrentCategory then if Data.CurrentCategory then for key, button in pairs(Data.CurrentCategory) do button.Visible = false end end Data.CurrentCategory = buttons if Data.Category[Data.CurrentCategory] == nil then Data.Category[Data.CurrentCategory] = {} if #buttons > 0 then selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0) end else Data.Category[Data.CurrentCategory].Button = nil selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index) end end end local function selectCategory(category) selectCategoryPage(category, 0) end local function resetAllSetButtonSelection() local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren() for i = 1, #setButtons do if setButtons[i]:IsA("TextButton") then setButtons[i].Selected = false setButtons[i].BackgroundTransparency = 1 setButtons[i].TextColor3 = Color3.new(1,1,1) setButtons[i].BackgroundColor3 = Color3.new(1,1,1) end end end local function populateSetsFrame() local currRow = 0 for i = 1, #userCategoryButtons do local button = userCategoryButtons[i] button.Visible = true button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset) button.Parent = setGui.SetPanel.Sets.SetsLists if i == 1 then -- we will have this selected by default, so show it button.Selected = true button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 end button.MouseEnter:connect(function() if not button.Selected then button.BackgroundTransparency = 0 button.TextColor3 = Color3.new(0,0,0) end end) button.MouseLeave:connect(function() if not button.Selected then button.BackgroundTransparency = 1 button.TextColor3 = Color3.new(1,1,1) end end) button.MouseButton1Click:connect(function() resetAllSetButtonSelection() button.Selected = not button.Selected button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0) end) currRow = currRow + 1 end local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren() -- set first category as loaded for default if buttons then for i = 1, #buttons do if buttons[i]:IsA("TextButton") then selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0) selectCategory(userCategoryButtons) break end end end end setGui = createSetGui() waterGui, waterTypeChangedEvent = createWaterGui() waterGui.Position = UDim2.new(0,55,0,0) waterGui.Parent = setGui setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size if prop == "AbsoluteSize" then handleResize() setSetIndex() end end) local scrollFrame, controlFrame = t.CreateTrueScrollingFrame() scrollFrame.Size = UDim2.new(0.54,0,0.85,0) scrollFrame.Position = UDim2.new(0.24,0,0.085,0) scrollFrame.Name = "ItemsFrame" scrollFrame.ZIndex = 6 scrollFrame.Parent = setGui.SetPanel scrollFrame.BackgroundTransparency = 1 drillDownSetZIndex(controlFrame,7) controlFrame.Parent = setGui.SetPanel controlFrame.Position = UDim2.new(0.76, 5, 0, 0) local debounce = false controlFrame.ScrollBottom.Changed:connect(function(prop) if controlFrame.ScrollBottom.Value == true then if debounce then return end debounce = true loadSectionOfItems(setGui, rows, columns) debounce = false end end) local userData = {} for id = 1, #userIdsForSets do local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id]) if newUserData and #newUserData > 2 then -- start at #3 to skip over My Decals and My Models for each account for category = 3, #newUserData do if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first table.insert(userData,1,newUserData[category]) else table.insert(userData, newUserData[category]) end end end end if userData then userCategoryButtons = processCategory(userData) end rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight) columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) populateSetsFrame() insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function() setGui.SetPanel.Visible = false if dialogClosed then dialogClosed() end end) local setVisibilityFunction = function(visible) if visible then setGui.SetPanel.Visible = true else setGui.SetPanel.Visible = false end end local getVisibilityFunction = function() if setGui then if setGui:FindFirstChild("SetPanel") then return setGui.SetPanel.Visible end end return false end return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent end t.CreateTerrainMaterialSelector = function(size,position) local terrainMaterialSelectionChanged = Instance.new("BindableEvent") terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged" local selectedButton = nil local frame = Instance.new("Frame") frame.Name = "TerrainMaterialSelector" if size then frame.Size = size else frame.Size = UDim2.new(0, 245, 0, 230) end if position then frame.Position = position end frame.BorderSizePixel = 0 frame.BackgroundColor3 = Color3.new(0,0,0) frame.Active = true terrainMaterialSelectionChanged.Parent = frame local waterEnabled = true -- todo: turn this on when water is ready local materialToImageMap = {} local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"} if waterEnabled then table.insert(materialNames,"Water") end local currentMaterial = 1 function getEnumFromName(choice) if choice == "Grass" then return 1 end if choice == "Sand" then return 2 end if choice == "Erase" then return 0 end if choice == "Brick" then return 3 end if choice == "Granite" then return 4 end if choice == "Asphalt" then return 5 end if choice == "Iron" then return 6 end if choice == "Aluminum" then return 7 end if choice == "Gold" then return 8 end if choice == "Plank" then return 9 end if choice == "Log" then return 10 end if choice == "Gravel" then return 11 end if choice == "Cinder Block" then return 12 end if choice == "Stone Wall" then return 13 end if choice == "Concrete" then return 14 end if choice == "Plastic (red)" then return 15 end if choice == "Plastic (blue)" then return 16 end if choice == "Water" then return 17 end end function getNameFromEnum(choice) if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end if waterEnabled then if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end end end local function updateMaterialChoice(choice) currentMaterial = getEnumFromName(choice) terrainMaterialSelectionChanged:Fire(currentMaterial) end -- we so need a better way to do this for i,v in pairs(materialNames) do materialToImageMap[v] = {} if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112" elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652" elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537" elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153" elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038" elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093" elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995" elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118" elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848" elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924" elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015" elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051" elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206" elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103" elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804" elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059" elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474" else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!! end end local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid") scrollFrame.Size = UDim2.new(0.85,0,1,0) scrollFrame.Position = UDim2.new(0,0,0,0) scrollFrame.Parent = frame scrollUp.Parent = frame scrollUp.Visible = true scrollUp.Position = UDim2.new(1,-19,0,0) scrollDown.Parent = frame scrollDown.Visible = true scrollDown.Position = UDim2.new(1,-19,1,-17) local function goToNewMaterial(buttonWrap, materialName) updateMaterialChoice(materialName) buttonWrap.BackgroundTransparency = 0 selectedButton.BackgroundTransparency = 1 selectedButton = buttonWrap end local function createMaterialButton(name) local buttonWrap = Instance.new("TextButton") buttonWrap.Text = "" buttonWrap.Size = UDim2.new(0,32,0,32) buttonWrap.BackgroundColor3 = Color3.new(1,1,1) buttonWrap.BorderSizePixel = 0 buttonWrap.BackgroundTransparency = 1 buttonWrap.AutoButtonColor = false buttonWrap.Name = tostring(name) local imageButton = Instance.new("ImageButton") imageButton.AutoButtonColor = false imageButton.BackgroundTransparency = 1 imageButton.Size = UDim2.new(0,30,0,30) imageButton.Position = UDim2.new(0,1,0,1) imageButton.Name = tostring(name) imageButton.Parent = buttonWrap imageButton.Image = materialToImageMap[name].Regular local enumType = Instance.new("NumberValue") enumType.Name = "EnumType" enumType.Parent = buttonWrap enumType.Value = 0 imageButton.MouseEnter:connect(function() buttonWrap.BackgroundTransparency = 0 end) imageButton.MouseLeave:connect(function() if selectedButton ~= buttonWrap then buttonWrap.BackgroundTransparency = 1 end end) imageButton.MouseButton1Click:connect(function() if selectedButton ~= buttonWrap then goToNewMaterial(buttonWrap, tostring(name)) end end) return buttonWrap end for i = 1, #materialNames do local imageButton = createMaterialButton(materialNames[i]) if materialNames[i] == "Grass" then -- always start with grass as the default selectedButton = imageButton imageButton.BackgroundTransparency = 0 end imageButton.Parent = scrollFrame end local forceTerrainMaterialSelection = function(newMaterialType) if not newMaterialType then return end if currentMaterial == newMaterialType then return end local matName = getNameFromEnum(newMaterialType) local buttons = scrollFrame:GetChildren() for i = 1, #buttons do if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end if string.find(buttons[i].Name, matName) then goToNewMaterial(buttons[i],matName) return end end end frame.Changed:connect(function ( prop ) if prop == "AbsoluteSize" then recalculateScroll() end end) recalculateScroll() return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection end t.CreateLoadingFrame = function(name,size,position) game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053") local loadingFrame = Instance.new("Frame") loadingFrame.Name = "LoadingFrame" loadingFrame.Style = Enum.FrameStyle.RobloxRound if size then loadingFrame.Size = size else loadingFrame.Size = UDim2.new(0,300,0,160) end if position then loadingFrame.Position = position else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end local loadingBar = Instance.new("Frame") loadingBar.Name = "LoadingBar" loadingBar.BackgroundColor3 = Color3.new(0,0,0) loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255) loadingBar.Position = UDim2.new(0,0,0,41) loadingBar.Size = UDim2.new(1,0,0,30) loadingBar.Parent = loadingFrame local loadingGreenBar = Instance.new("ImageLabel") loadingGreenBar.Name = "LoadingGreenBar" loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053" loadingGreenBar.Position = UDim2.new(0,0,0,0) loadingGreenBar.Size = UDim2.new(0,0,1,0) loadingGreenBar.Visible = false loadingGreenBar.Parent = loadingBar local loadingPercent = Instance.new("TextLabel") loadingPercent.Name = "LoadingPercent" loadingPercent.BackgroundTransparency = 1 loadingPercent.Position = UDim2.new(0,0,1,0) loadingPercent.Size = UDim2.new(1,0,0,14) loadingPercent.Font = Enum.Font.Arial loadingPercent.Text = "0%" loadingPercent.FontSize = Enum.FontSize.Size14 loadingPercent.TextColor3 = Color3.new(1,1,1) loadingPercent.Parent = loadingBar local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(0.5,-60,1,-40) cancelButton.Size = UDim2.new(0,120,0,40) cancelButton.Font = Enum.Font.Arial cancelButton.FontSize = Enum.FontSize.Size18 cancelButton.TextColor3 = Color3.new(1,1,1) cancelButton.Text = "Cancel" cancelButton.Style = Enum.ButtonStyle.RobloxButton cancelButton.Parent = loadingFrame local loadingName = Instance.new("TextLabel") loadingName.Name = "loadingName" loadingName.BackgroundTransparency = 1 loadingName.Size = UDim2.new(1,0,0,18) loadingName.Position = UDim2.new(0,0,0,2) loadingName.Font = Enum.Font.Arial loadingName.Text = name loadingName.TextColor3 = Color3.new(1,1,1) loadingName.TextStrokeTransparency = 1 loadingName.FontSize = Enum.FontSize.Size18 loadingName.Parent = loadingFrame local cancelButtonClicked = Instance.new("BindableEvent") cancelButtonClicked.Name = "CancelButtonClicked" cancelButtonClicked.Parent = cancelButton cancelButton.MouseButton1Click:connect(function() cancelButtonClicked:Fire() end) local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength) if percent and type(percent) ~= "number" then error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead") end local newSize = nil if percent < 0 then newSize = UDim2.new(0,0,1,0) elseif percent > 1 then newSize = UDim2.new(1,0,1,0) else newSize = UDim2.new(percent,0,1,0) end if tweenAction then if not tweenLength then error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument") end if (newSize.X.Scale > 0) then loadingGreenBar.Visible = true loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true) else loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true, function() if (newSize.X.Scale < 0) then loadingGreenBar.Visible = false end end) end else loadingGreenBar.Size = newSize loadingGreenBar.Visible = (newSize.X.Scale > 0) end end loadingGreenBar.Changed:connect(function(prop) if prop == "Size" then loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%" end end) return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked end t.CreatePluginFrame = function (name,size,position,scrollable,parent) function createMenuButton(size,position,text,fontsize,name,parent) local button = Instance.new("TextButton",parent) button.AutoButtonColor = false button.Name = name button.BackgroundTransparency = 1 button.Position = position button.Size = size button.Font = Enum.Font.ArialBold button.FontSize = fontsize button.Text = text button.TextColor3 = Color3.new(1,1,1) button.BorderSizePixel = 0 button.BackgroundColor3 = Color3.new(20/255,20/255,20/255) button.MouseEnter:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 1 end) return button end local dragBar = Instance.new("Frame",parent) dragBar.Name = tostring(name) .. "DragBar" dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) dragBar.BorderColor3 = Color3.new(0,0,0) if size then dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0) else dragBar.Size = UDim2.new(0,183,0,20) end if position then dragBar.Position = position end dragBar.Active = true dragBar.Draggable = true --dragBar.Visible = false dragBar.MouseEnter:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255) end) dragBar.MouseLeave:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) end) -- plugin name label local pluginNameLabel = Instance.new("TextLabel",dragBar) pluginNameLabel.Name = "BarNameLabel" pluginNameLabel.Text = " " .. tostring(name) pluginNameLabel.TextColor3 = Color3.new(1,1,1) pluginNameLabel.TextStrokeTransparency = 0 pluginNameLabel.Size = UDim2.new(1,0,1,0) pluginNameLabel.Font = Enum.Font.ArialBold pluginNameLabel.FontSize = Enum.FontSize.Size18 pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left pluginNameLabel.BackgroundTransparency = 1 -- close button local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar) local closeEvent = Instance.new("BindableEvent") closeEvent.Name = "CloseEvent" closeEvent.Parent = closeButton closeButton.MouseButton1Click:connect(function () closeEvent:Fire() closeButton.BackgroundTransparency = 1 end) -- help button local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar) local helpFrame = Instance.new("Frame",dragBar) helpFrame.Name = "HelpFrame" helpFrame.BackgroundColor3 = Color3.new(0,0,0) helpFrame.Size = UDim2.new(0,300,0,552) helpFrame.Position = UDim2.new(1,5,0,0) helpFrame.Active = true helpFrame.BorderSizePixel = 0 helpFrame.Visible = false helpButton.MouseButton1Click:connect(function( ) helpFrame.Visible = not helpFrame.Visible if helpFrame.Visible then helpButton.Selected = true helpButton.BackgroundTransparency = 0 local screenGui = getScreenGuiAncestor(helpFrame) if screenGui then if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0) else -- position on right hand side helpFrame.Position = UDim2.new(1,5,0,0) end else helpFrame.Position = UDim2.new(1,5,0,0) end else helpButton.Selected = false helpButton.BackgroundTransparency = 1 end end) local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar) minimizeButton.TextYAlignment = Enum.TextYAlignment.Top local minimizeFrame = Instance.new("Frame",dragBar) minimizeFrame.Name = "MinimizeFrame" minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255) minimizeFrame.BorderColor3 = Color3.new(0,0,0) minimizeFrame.Position = UDim2.new(0,0,1,0) if size then minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0) else minimizeFrame.Size = UDim2.new(0,183,0,50) end minimizeFrame.Visible = false local minimizeBigButton = Instance.new("TextButton",minimizeFrame) minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20) minimizeBigButton.Name = "MinimizeButton" minimizeBigButton.Size = UDim2.new(0,100,0,40) minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton minimizeBigButton.Font = Enum.Font.ArialBold minimizeBigButton.FontSize = Enum.FontSize.Size18 minimizeBigButton.TextColor3 = Color3.new(1,1,1) minimizeBigButton.Text = "Show" local separatingLine = Instance.new("Frame",dragBar) separatingLine.Name = "SeparatingLine" separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255) separatingLine.BorderSizePixel = 0 separatingLine.Position = UDim2.new(1,-18,0.5,-7) separatingLine.Size = UDim2.new(0,1,0,14) local otherSeparatingLine = separatingLine:clone() otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7) otherSeparatingLine.Parent = dragBar local widgetContainer = Instance.new("Frame",dragBar) widgetContainer.Name = "WidgetContainer" widgetContainer.BackgroundTransparency = 1 widgetContainer.Position = UDim2.new(0,0,1,0) widgetContainer.BorderColor3 = Color3.new(0,0,0) if not scrollable then widgetContainer.BackgroundTransparency = 0 widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255) end if size then if scrollable then widgetContainer.Size = size else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset) end else if scrollable then widgetContainer.Size = UDim2.new(0,163,0,400) else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400) end end if position then widgetContainer.Position = position + UDim2.new(0,0,0,20) end local frame,control,verticalDragger = nil if scrollable then --frame for widgets frame,control = t.CreateTrueScrollingFrame() frame.Size = UDim2.new(1, 0, 1, 0) frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255) frame.BorderColor3 = Color3.new(0,0,0) frame.Active = true frame.Parent = widgetContainer control.Parent = dragBar control.BackgroundColor3 = Color3.new(72/255,72/255,72/255) control.BorderSizePixel = 0 control.BackgroundTransparency = 0 control.Position = UDim2.new(1,-21,1,1) if size then control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset) else control.Size = UDim2.new(0,21,0,400) end control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20) local fakeLine = Instance.new("Frame",control) fakeLine.Name = "FakeLine" fakeLine.BorderSizePixel = 0 fakeLine.BackgroundColor3 = Color3.new(0,0,0) fakeLine.Size = UDim2.new(0,1,1,1) fakeLine.Position = UDim2.new(1,0,0,0) verticalDragger = Instance.new("TextButton",widgetContainer) verticalDragger.ZIndex = 2 verticalDragger.AutoButtonColor = false verticalDragger.Name = "VerticalDragger" verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) verticalDragger.BorderColor3 = Color3.new(0,0,0) verticalDragger.Size = UDim2.new(1,20,0,20) verticalDragger.Position = UDim2.new(0,0,1,0) verticalDragger.Active = true verticalDragger.Text = "" local scrubFrame = Instance.new("Frame",verticalDragger) scrubFrame.Name = "ScrubFrame" scrubFrame.BackgroundColor3 = Color3.new(1,1,1) scrubFrame.BorderSizePixel = 0 scrubFrame.Position = UDim2.new(0.5,-5,0.5,0) scrubFrame.Size = UDim2.new(0,10,0,1) scrubFrame.ZIndex = 5 local scrubTwo = scrubFrame:clone() scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2) scrubTwo.Parent = verticalDragger local scrubThree = scrubFrame:clone() scrubThree.Position = UDim2.new(0.5,-5,0.5,2) scrubThree.Parent = verticalDragger local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent)) areaSoak.Name = "AreaSoak" areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.BackgroundTransparency = 1 areaSoak.BorderSizePixel = 0 areaSoak.Text = "" areaSoak.ZIndex = 10 areaSoak.Visible = false areaSoak.Active = true local draggingVertical = false local startYPos = nil verticalDragger.MouseEnter:connect(function () verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255) end) verticalDragger.MouseLeave:connect(function () verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) end) verticalDragger.MouseButton1Down:connect(function(x,y) draggingVertical = true areaSoak.Visible = true startYPos = y end) areaSoak.MouseButton1Up:connect(function ( ) draggingVertical = false areaSoak.Visible = false end) areaSoak.MouseMoved:connect(function(x,y) if not draggingVertical then return end local yDelta = y - startYPos if not control.ScrollDownButton.Visible and yDelta > 0 then return end if (widgetContainer.Size.Y.Offset + yDelta) < 150 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150) control.Size = UDim2.new (0,21,0,150) return end startYPos = y if widgetContainer.Size.Y.Offset + yDelta >= 0 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta) control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta ) end end) end local function switchMinimize() minimizeFrame.Visible = not minimizeFrame.Visible if scrollable then frame.Visible = not frame.Visible verticalDragger.Visible = not verticalDragger.Visible control.Visible = not control.Visible else widgetContainer.Visible = not widgetContainer.Visible end if minimizeFrame.Visible then minimizeButton.Text = "+" else minimizeButton.Text = "-" end end minimizeBigButton.MouseButton1Click:connect(function ( ) switchMinimize() end) minimizeButton.MouseButton1Click:connect(function( ) switchMinimize() end) if scrollable then return dragBar, frame, helpFrame, closeEvent else return dragBar, widgetContainer, helpFrame, closeEvent end end t.Help = function(funcNameOrFunc) --input argument can be a string or a function. Should return a description (of arguments and expected side effects) if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then return "Function CreatePropertyDropDownMenu. " .. "Arguments: (instance, propertyName, enumType). " .. "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'" end if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then return "Function CreateDropDownMenu. " .. "Arguments: (items, onItemSelected). " .. "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items" end if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then return "Function CreateMessageDialog. " .. "Arguments: (title, message, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button" end if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then return "Function CreateStyledMessageDialog. " .. "Arguments: (title, message, style, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm" end if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then return "Function GetFontHeight. " .. "Arguments: (font, fontSize). " .. "Side effect: returns the size in pixels of the given font + fontSize" end if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then end if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then return "Function CreateScrollingFrame. " .. "Arguments: (orderList, style) " .. "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)" end if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then return "Function CreateTrueScrollingFrame. " .. "Arguments: (nil) " .. "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit." end if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then return "Function AutoTruncateTextObject. " .. "Arguments: (textLabel) " .. "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument" end if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then return "Function CreateSlider. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then return "Function CreateSliderNew. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then return "Function CreateLoadingFrame. " .. "Arguments: (name, size, position) " .. "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog." end if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then return "Function CreateTerrainMaterialSelector. " .. "Arguments: (size, position) " .. "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected." end end -- A couple of necessary functions local function waitForChild(instance, name) assert(instance) assert(name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end return instance:FindFirstChild(name) end local function waitForProperty(instance, property) assert(instance) assert(property) while not instance[property] do instance.Changed:wait() end end local function IsTouchDevice() --return Game:GetService('UserInputService').TouchEnabled end waitForChild(game,"Players") waitForProperty(game.Players,"LocalPlayer") local player = game.Players.LocalPlayer local RbxGui, msg = t if not RbxGui then print("could not find RbxGui!") return end --- Begin Locals local StaticTabName = "gear" local backpack = script.Parent.Backpack local screen = script.Parent local backpackItems = {} local buttons = {} local debounce = false local browsingMenu = false local mouseEnterCons = {} local mouseClickCons = {} local characterChildAddedCon = nil local characterChildRemovedCon = nil local backpackAddCon = nil local playerBackpack = waitForChild(player,"Backpack") waitForChild(backpack,"Gear") local gearPreview = waitForChild(backpack.Gear,"GearPreview") local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea") local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout") local grid = waitForChild(backpack.Gear,"GearGrid") local gearButton = waitForChild(grid,"GearButton") local swapSlot = waitForChild(script.Parent,"SwapSlot") local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager") local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent") local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent") local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent") local resizeEvent = waitForChild(backpackManager,"ResizeEvent") local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent") local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady") -- creating scroll bar early as to make sure items get placed correctly local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(6, 6)) scrollFrame.Position = UDim2.new(0,0,0,30) scrollFrame.Size = UDim2.new(1,0,1,-30) scrollFrame.Parent = backpack.Gear.GearGrid local scrollBar = Instance.new("Frame") scrollBar.Name = "ScrollBar" scrollBar.BackgroundTransparency = 0.9 scrollBar.BackgroundColor3 = Color3.new(1,1,1) scrollBar.BorderSizePixel = 0 scrollBar.Size = UDim2.new(0, 17, 1, -36) scrollBar.Position = UDim2.new(0,0,0,18) scrollBar.Parent = scroller scrollDown.Position = UDim2.new(0,0,1,-17) scrollUp.Parent = scroller scrollDown.Parent = scroller local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame() scrollFrameLoadout.Position = UDim2.new(0,0,0,0) scrollFrameLoadout.Size = UDim2.new(1,0,1,0) scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList local LoadoutButton = Instance.new("TextButton") LoadoutButton.Name = "LoadoutButton" LoadoutButton.Font = Enum.Font.ArialBold LoadoutButton.FontSize = Enum.FontSize.Size14 LoadoutButton.Position = UDim2.new(0,0,0,0) LoadoutButton.Size = UDim2.new(1,0,0,32) LoadoutButton.Style = Enum.ButtonStyle.RobloxButton LoadoutButton.Text = "Loadout #1" LoadoutButton.TextColor3 = Color3.new(1,1,1) LoadoutButton.Parent = scrollFrameLoadout local LoadoutButtonTwo = LoadoutButton:clone() LoadoutButtonTwo.Text = "Loadout #2" LoadoutButtonTwo.Parent = scrollFrameLoadout local LoadoutButtonThree = LoadoutButton:clone() LoadoutButtonThree.Text = "Loadout #3" LoadoutButtonThree.Parent = scrollFrameLoadout local LoadoutButtonFour = LoadoutButton:clone() LoadoutButtonFour.Text = "Loadout #4" LoadoutButtonFour.Parent = scrollFrameLoadout local scrollBarLoadout = Instance.new("Frame") scrollBarLoadout.Name = "ScrollBarLoadout" scrollBarLoadout.BackgroundTransparency = 0.9 scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1) scrollBarLoadout.BorderSizePixel = 0 scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36) scrollBarLoadout.Position = UDim2.new(0,0,0,18) scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea scrollDownLoadout.Position = UDim2.new(0,0,1,-17) scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea -- Begin Functions function removeFromMap(map,object) for i = 1, #map do if map[i] == object then table.remove(map,i) break end end end function robloxLock(instance) end function resize() local size = 0 if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then size = gearPreview.AbsoluteSize.X * 0.75 else size = gearPreview.AbsoluteSize.Y * 0.75 end waitForChild(gearPreview,"GearImage") gearPreview.GearImage.Size = UDim2.new(0,size,0,size) gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size) resizeGrid() end function addToGrid(child) if not child:IsA("Tool") then if not child:IsA("HopperBin") then return end end if child:FindFirstChild("RobloxBuildTool") then return end for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered if v == child then return end end table.insert(backpackItems,child) local changeCon = child.Changed:connect(function(prop) if prop == "Name" then if buttons[child] then if buttons[child].Image == "" then buttons[child].GearText.Text = child.Name end end end end) local ancestryCon = nil ancestryCon = child.AncestryChanged:connect(function(theChild,theParent) local thisObject = nil for k,v in pairs(backpackItems) do if v == child then thisObject = v break end end waitForProperty(player,"Character") waitForChild(player,"Backpack") if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then if ancestryCon then ancestryCon:disconnect() end if changeCon then changeCon:disconnect() end for k,v in pairs(backpackItems) do if v == thisObject then if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end buttons[v].Parent = nil buttons[v] = nil break end end removeFromMap(backpackItems,thisObject) resizeGrid() else resizeGrid() end updateGridActive() end) resizeGrid() end function buttonClick(button) if button:FindFirstChild("UnequipContextMenu") and not button.Active then button.UnequipContextMenu.Visible = true browsingMenu = true end end function previewGear(button) if not browsingMenu then gearPreview.Visible = false gearPreview.GearImage.Image = button.Image gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name end end function findEmptySlot() local smallestNum = nil local loadout = currentLoadout:GetChildren() for i = 1, #loadout do if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then local frameNum = tonumber(string.sub(loadout[i].Name,5)) if frameNum == 0 then frameNum = 10 end if not smallestNum or (smallestNum > frameNum) then smallestNum = frameNum end end end if smallestNum == 10 then smallestNum = 0 end return smallestNum end function checkForSwap(button,x,y) local loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) swapGearSlot(slot,button) return true end end end end return false end function resizeGrid() for k,v in pairs(backpackItems) do if not v:FindFirstChild("RobloxBuildTool") then if not buttons[v] then local buttonClone = gearButton:clone() buttonClone.Parent = grid.ScrollingFrame buttonClone.Visible = true buttonClone.Image = v.TextureId if buttonClone.Image == "" then buttonClone.GearText.Text = v.Name end buttonClone.GearReference.Value = v buttonClone.Draggable = true buttons[v] = buttonClone if not IsTouchDevice() then local unequipMenu = getGearContextMenu() unequipMenu.Visible = false unequipMenu.Parent = buttonClone end local beginPos = nil buttonClone.DragBegin:connect(function(value) waitForChild(buttonClone, 'Background') buttonClone['Background'].ZIndex = 10 buttonClone.ZIndex = 10 beginPos = value end) buttonClone.DragStopped:connect(function(x,y) waitForChild(buttonClone, 'Background') buttonClone['Background'].ZIndex = 1.0 buttonClone.ZIndex = 2 if beginPos ~= buttonClone.Position then if not checkForSwap(buttonClone,x,y) then buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true) buttonClone.Draggable = false delay(0.5,function() buttonClone.Draggable = true end) else buttonClone.Position = beginPos end end end) local clickTime = tick() mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end) mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() local newClickTime = tick() if buttonClone.Active and (newClickTime - clickTime) < 0.5 then local slot = findEmptySlot() if slot then buttonClone.ZIndex = 1 swapGearSlot(slot,buttonClone) end else buttonClick(buttonClone) end clickTime = newClickTime end) end end end recalculateScroll() end function showPartialGrid(subset) for k,v in pairs(buttons) do v.Parent = nil end if subset then for k,v in pairs(subset) do v.Parent = grid.ScrollingFrame end end recalculateScroll() end function showEntireGrid() for k,v in pairs(buttons) do v.Parent = grid.ScrollingFrame end recalculateScroll() end function inLoadout(gear) local children = currentLoadout:GetChildren() for i = 1, #children do if children[i]:IsA("Frame") then local button = children[i]:GetChildren() if #button > 0 then if button[1].GearReference.Value and button[1].GearReference.Value == gear then return true end end end end return false end function updateGridActive() for k,v in pairs(backpackItems) do if buttons[v] then local gear = nil local gearRef = buttons[v]:FindFirstChild("GearReference") if gearRef then gear = gearRef.Value end if not gear then buttons[v].Active = false elseif inLoadout(gear) then buttons[v].Active = false else buttons[v].Active = true end end end end function centerGear(loadoutChildren) local gearButtons = {} local lastSlotAdd = nil for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then if loadoutChildren[i].Name == "Slot0" then lastSlotAdd = loadoutChildren[i] else table.insert(gearButtons, loadoutChildren[i]) end end end if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end local startPos = ( 1 - (#gearButtons * 0.1) ) / 2 for i = 1, #gearButtons do gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) end end function tabClickHandler(tabName) if tabName == StaticTabName then backpackOpenHandler(tabName) else backpackCloseHandler(tabName) end end function backpackOpenHandler(currentTab) if currentTab and currentTab ~= StaticTabName then backpack.Gear.Visible = false return end backpack.Gear.Visible = true updateGridActive() resizeGrid() resize() tellBackpackReadyFunc:Invoke() end function backpackCloseHandler(currentTab) if currentTab and currentTab ~= StaticTabName then backpack.Gear.Visible = false return end backpack.Gear.Visible = false resizeGrid() resize() tellBackpackReadyFunc:Invoke() end function loadoutCheck(child, selectState) if not child:IsA("ImageButton") then return end for k,v in pairs(backpackItems) do if buttons[v] then if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then if buttons[v].GearReference.Value == child.GearReference.Value then buttons[v].Active = selectState break end end end end end function clearPreview() gearPreview.GearImage.Image = "" gearPreview.GearStats.GearName.Text = "" end function removeAllEquippedGear(physGear) local stuff = player.Character:GetChildren() for i = 1, #stuff do if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then stuff[i].Parent = playerBackpack end end end function equipGear(physGear) removeAllEquippedGear(physGear) physGear.Parent = player.Character updateGridActive() end function unequipGear(physGear) physGear.Parent = playerBackpack updateGridActive() end function highlight(button) button.TextColor3 = Color3.new(0,0,0) button.BackgroundColor3 = Color3.new(0.8,0.8,0.8) end function clearHighlight(button) button.TextColor3 = Color3.new(1,1,1) button.BackgroundColor3 = Color3.new(0,0,0) end function swapGearSlot(slot,gearButton) if not swapSlot.Value then -- signal loadout to swap a gear out swapSlot.Slot.Value = slot swapSlot.GearButton.Value = gearButton swapSlot.Value = true updateGridActive() end end local UnequipGearMenuClick = function(element, menu) if type(element.Action) ~= "number" then return end local num = element.Action if num == 1 then -- remove from loadout unequipGear(menu.Parent.GearReference.Value) local inventoryButton = menu.Parent local gearToUnequip = inventoryButton.GearReference.Value local loadoutChildren = currentLoadout:GetChildren() local slot = -1 for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then local button = loadoutChildren[i]:GetChildren() if button[1] and button[1].GearReference.Value == gearToUnequip then slot = button[1].SlotNumber.Text break end end end swapGearSlot(slot,nil) end end function setupCharacterConnections() if backpackAddCon then backpackAddCon:disconnect() end backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) -- make sure we get all the children local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren() for i = 1, #backpackChildren do addToGrid(backpackChildren[i]) end if characterChildAddedCon then characterChildAddedCon:disconnect() end characterChildAddedCon = game.Players.LocalPlayer.Character.ChildAdded:connect(function(child) addToGrid(child) updateGridActive() end) if characterChildRemovedCon then characterChildRemovedCon:disconnect() end characterChildRemovedCon = game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child) updateGridActive() end) wait() centerGear(currentLoadout:GetChildren()) end function removeCharacterConnections() if characterChildAddedCon then characterChildAddedCon:disconnect() end if characterChildRemovedCon then characterChildRemovedCon:disconnect() end if backpackAddCon then backpackAddCon:disconnect() end end function trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end function filterGear(terms) local filteredGear = {} for k,v in pairs(backpackItems) do if buttons[v] then local gearString = string.lower(buttons[v].GearReference.Value.Name) gearString = trim(gearString) for i = 1, #terms do if string.match(gearString,terms[i]) then table.insert(filteredGear,buttons[v]) break end end end end return filteredGear end function splitByWhitespace(text) if type(text) ~= "string" then return nil end local terms = {} for token in string.gmatch(text, "[^%s]+") do if string.len(token) > 0 then table.insert(terms,token) end end return terms end function showSearchGear(searchTerms) if not backpack.Gear.Visible then return end -- currently not active tab local searchTermTable = splitByWhitespace(searchTerms) if searchTermTable and (#searchTermTable > 0) then currSearchTerms = searchTermTable else currSearchTerms = nil end if searchTermTable == nil then showEntireGrid() return end local filteredButtons = filterGear(currSearchTerms) showPartialGrid(filteredButtons) end function nukeBackpack() while #buttons > 0 do table.remove(buttons) end buttons = {} while #backpackItems > 0 do table.remove(backpackItems) end backpackItems = {} local scrollingFrameChildren = grid.ScrollingFrame:GetChildren() for i = 1, #scrollingFrameChildren do scrollingFrameChildren[i]:remove() end end function getGearContextMenu() local gearContextMenu = Instance.new("Frame") gearContextMenu.Active = true gearContextMenu.Name = "UnequipContextMenu" gearContextMenu.Size = UDim2.new(0,115,0,70) gearContextMenu.Position = UDim2.new(0,-16,0,-16) gearContextMenu.BackgroundTransparency = 1 gearContextMenu.Visible = false local gearContextMenuButton = Instance.new("TextButton") gearContextMenuButton.Name = "UnequipContextMenuButton" gearContextMenuButton.Text = "" gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault gearContextMenuButton.ZIndex = 8 gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20) gearContextMenuButton.Visible = true gearContextMenuButton.Parent = gearContextMenu local elementHeight = 12 local contextMenuElements = {} local contextMenuElementsName = {"Remove Hotkey"} for i = 1, #contextMenuElementsName do local element = {} element.Type = "Button" element.Text = contextMenuElementsName[i] element.Action = i element.DoIt = UnequipGearMenuClick table.insert(contextMenuElements,element) end for i, contextElement in ipairs(contextMenuElements) do local element = contextElement if element.Type == "Button" then local button = Instance.new("TextButton") button.Name = "UnequipContextButton" .. i button.BackgroundColor3 = Color3.new(0,0,0) button.BorderSizePixel = 0 button.TextXAlignment = Enum.TextXAlignment.Left button.Text = " " .. contextElement.Text button.Font = Enum.Font.Arial button.FontSize = Enum.FontSize.Size14 button.Size = UDim2.new(1, 8, 0, elementHeight) button.Position = UDim2.new(0,0,0,elementHeight * i) button.TextColor3 = Color3.new(1,1,1) button.ZIndex = 9 button.Parent = gearContextMenuButton if not IsTouchDevice() then button.MouseButton1Click:connect(function() if button.Active and not gearContextMenu.Parent.Active then local success, result = pcall(function() element.DoIt(element, gearContextMenu) end) browsingMenu = false gearContextMenu.Visible = false clearHighlight(button) clearPreview() end end) button.MouseEnter:connect(function() if button.Active and gearContextMenu.Parent.Active then highlight(button) end end) button.MouseLeave:connect(function() if button.Active and gearContextMenu.Parent.Active then clearHighlight(button) end end) end contextElement.Button = button contextElement.Element = button elseif element.Type == "Label" then local frame = Instance.new("Frame") frame.Name = "ContextLabel" .. i frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1, 8, 0, elementHeight) local label = Instance.new("TextLabel") label.Name = "Text1" label.BackgroundTransparency = 1 label.BackgroundColor3 = Color3.new(1,1,1) label.BorderSizePixel = 0 label.TextXAlignment = Enum.TextXAlignment.Left label.Font = Enum.Font.ArialBold label.FontSize = Enum.FontSize.Size14 label.Position = UDim2.new(0.0, 0, 0, 0) label.Size = UDim2.new(0.5, 0, 1, 0) label.TextColor3 = Color3.new(1,1,1) label.ZIndex = 9 label.Parent = frame element.Label1 = label if element.GetText2 then label = Instance.new("TextLabel") label.Name = "Text2" label.BackgroundTransparency = 1 label.BackgroundColor3 = Color3.new(1,1,1) label.BorderSizePixel = 0 label.TextXAlignment = Enum.TextXAlignment.Right label.Font = Enum.Font.Arial label.FontSize = Enum.FontSize.Size14 label.Position = UDim2.new(0.5, 0, 0, 0) label.Size = UDim2.new(0.5, 0, 1, 0) label.TextColor3 = Color3.new(1,1,1) label.ZIndex = 9 label.Parent = frame element.Label2 = label end frame.Parent = gearContextMenuButton element.Label = frame element.Element = frame end end gearContextMenu.ZIndex = 4 gearContextMenu.MouseLeave:connect(function() browsingMenu = false gearContextMenu.Visible = false clearPreview() end) return gearContextMenu end function coreGuiChanged(coreGuiType,enabled) if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then if not enabled then backpack.Gear.Visible = false end end end local backpackChildren = player.Backpack:GetChildren() for i = 1, #backpackChildren do addToGrid(backpackChildren[i]) end ------------------------- Start Lifelong Connections ----------------------- resizeEvent.Event:connect(function(absSize) if debounce then return end debounce = true wait() resize() resizeGrid() debounce = false end) currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end) currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end) currentLoadout.DescendantAdded:connect(function(descendant) if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then centerGear(currentLoadout:GetChildren()) end end) currentLoadout.DescendantRemoving:connect(function(descendant) if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then wait() centerGear(currentLoadout:GetChildren()) end end) grid.MouseEnter:connect(function() clearPreview() end) grid.MouseLeave:connect(function() clearPreview() end) player.CharacterRemoving:connect(function() removeCharacterConnections() nukeBackpack() end) player.CharacterAdded:connect(function() setupCharacterConnections() end) player.ChildAdded:connect(function(child) if child:IsA("Backpack") then playerBackpack = child if backpackAddCon then backpackAddCon:disconnect() end backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) end end) swapSlot.Changed:connect(function() if not swapSlot.Value then updateGridActive() end end) local loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then loadoutChildren[i].ChildRemoved:connect(function() updateGridActive() end) loadoutChildren[i].ChildAdded:connect(function() updateGridActive() end) end end ------------------------- End Lifelong Connections ----------------------- resize() resizeGrid() -- make sure any items in the loadout are accounted for in inventory local loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do loadoutCheck(loadoutChildren[i], false) end if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end -- make sure that inventory is listening to gear reparenting if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then setupCharacterConnections() end if not backpackAddCon then backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) end backpackOpenEvent.Event:connect(backpackOpenHandler) backpackCloseEvent.Event:connect(backpackCloseHandler) tabClickedEvent.Event:connect(tabClickHandler) searchRequestedEvent.Event:connect(showSearchGear) recalculateScrollLoadout() false BackpackManager -- basic functions local function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end return instance:FindFirstChild(name) end local function waitForProperty(instance, property) while not instance[property] do instance.Changed:wait() end end -- don't do anything if we are in an empty game waitForChild(game,"Players") if #game.Players:GetChildren() < 1 then game.Players.ChildAdded:wait() end -- make sure everything is loaded in before we do anything -- get our local player waitForProperty(game.Players,"LocalPlayer") local player = game.Players.LocalPlayer ------------------------ Locals ------------------------------ local backpack = script.Parent.Backpack waitForChild(backpack,"Gear") local screen = script.Parent assert(screen:IsA("ScreenGui")) waitForChild(backpack.Parent,"ControlFrame") local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton") local currentTab = "gear" local searchFrame = waitForChild(backpack,"SearchFrame") waitForChild(backpack.SearchFrame,"SearchBoxFrame") local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox") local searchButton = waitForChild(backpack.SearchFrame,"SearchButton") local resetButton = waitForChild(backpack.SearchFrame,"ResetButton") local robloxGui = script.Parent local currentLoadout = waitForChild(robloxGui, 'CurrentLoadout') local loadoutBackground = waitForChild(currentLoadout, 'Background') local canToggle = true local readyForNextEvent = true local backpackIsOpen = false local active = true local humanoidDiedCon = nil local backpackButtonPos local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack local searchDefaultText = "Search..." local tilde = "~" local backquote = "`" local backpackSize = UDim2.new(0, 600, 0, 400) ------------------------ End Locals --------------------------- ---------------------------------------- Public Event Setup ---------------------------------------- function createPublicEvent(eventName) assert(eventName, "eventName is nil") assert(tostring(eventName),"eventName is not a string") local newEvent = Instance.new("BindableEvent") newEvent.Name = tostring(eventName) newEvent.Parent = script return newEvent end function createPublicFunction(funcName, invokeFunc) assert(funcName, "funcName is nil") assert(tostring(funcName), "funcName is not a string") assert(invokeFunc, "invokeFunc is nil") assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'") local newFunction = Instance.new("BindableFunction") newFunction.Name = tostring(funcName) newFunction.OnInvoke = invokeFunc newFunction.Parent = script return newFunction end -- Events local resizeEvent = createPublicEvent("ResizeEvent") local backpackOpenEvent = createPublicEvent("BackpackOpenEvent") local backpackCloseEvent = createPublicEvent("BackpackCloseEvent") local tabClickedEvent = createPublicEvent("TabClickedEvent") local searchRequestedEvent = createPublicEvent("SearchRequestedEvent") ---------------------------------------- End Public Event Setup ---------------------------------------- --------------------------- Internal Functions ---------------------------------------- function deactivateBackpack() backpack.Visible = false active = false end function activateBackpack() initHumanoidDiedConnections() active = true backpack.Visible = backpackIsOpen if backpackIsOpen then toggleBackpack() end end function initHumanoidDiedConnections() if humanoidDiedCon then humanoidDiedCon:disconnect() end waitForProperty(game.Players.LocalPlayer,"Character") waitForChild(game.Players.LocalPlayer.Character,"Humanoid") humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack) end local hideBackpack = function() backpackIsOpen = false readyForNextEvent = false backpackButton.Selected = false resetSearch() backpackCloseEvent:Fire(currentTab) searchFrame.Visible = false backpack:TweenSizeAndPosition(UDim2.new(0, backpackSize.X.Offset,0, 0), UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -85), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true, function() game.GuiService:RemoveCenterDialog(backpack) backpack.Visible = false backpackButton.Selected = false end) delay(guiTweenSpeed,function() --game.GuiService:RemoveCenterDialog(backpack) backpack.Visible = false backpackButton.Selected = false readyForNextEvent = true canToggle = true end) end function spreadOutGear(loadoutChildren) for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) if slot == 0 then slot = 10 end loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) end end end function showBackpack() game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog, function() backpack.Visible = true backpackButton.Selected = true end, function() backpack.Visible = false backpackButton.Selected = false end) backpack.Visible = true backpack.Gear.Visible = true backpackButton.Selected = true backpack:TweenSizeAndPosition(backpackSize, UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -backpackSize.Y.Offset - 88), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true) delay(guiTweenSpeed,function() searchFrame.Visible = true --backpackOpenEvent:Fire(currentTab) canToggle = true readyForNextEvent = true backpackButton.Image = 'http://www.roblox.com/asset/?id=97644093' backpackButton.Position = UDim2.new(0.5, -60, 1, -backpackSize.Y.Offset - 103) loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then loadoutChildren[i].BackgroundTransparency = 0.5 end end spreadOutGear(loadoutChildren) end) end function toggleBackpack() if not game.Players.LocalPlayer then return end if not game.Players.LocalPlayer["Character"] then return end if not canToggle then return end if not readyForNextEvent then return end readyForNextEvent = false canToggle = false backpackIsOpen = not backpackIsOpen if backpackIsOpen then loadoutBackground.Image = 'http://www.roblox.com/asset/?id=97623721' loadoutBackground.Position = UDim2.new(-0.03, 0, -0.17, 0) loadoutBackground.Size = UDim2.new(1.05, 0, 1.25, 0) loadoutBackground.ZIndex = 2.0 loadoutBackground.Visible = true backpackButton.Position = UDim2.new(0.5, -60, 1, -503) showBackpack() else backpackButton.Position = UDim2.new(0.5, -60, 1, -44) loadoutBackground.Visible = false backpackButton.Selected = false backpackButton.Image = "http://www.roblox.com/asset/?id=97617958" loadoutBackground.Image = 'http://www.roblox.com/asset/?id=96536002' loadoutBackground.Position = UDim2.new(-0.1, 0, -0.1, 0) loadoutBackground.Size = UDim2.new(1.2, 0, 1.2, 0) hideBackpack() local clChildren = currentLoadout:GetChildren() for i = 1, #clChildren do if clChildren[i] and clChildren[i]:IsA('Frame') then local frame = clChildren[i] if #frame:GetChildren() > 0 then backpackButton.Position = UDim2.new(0.5, -60, 1, -108) backpackButton.Visible = true loadoutBackground.Visible = true if frame:GetChildren()[1]:IsA('ImageButton') then local imgButton = frame:GetChildren()[1] imgButton.Active = true imgButton.Draggable = false end end end end end end function closeBackpack() if backpackIsOpen then toggleBackpack() end end function setSelected(tab) assert(tab) assert(tab:IsA("TextButton")) tab.BackgroundColor3 = Color3.new(1,1,1) tab.TextColor3 = Color3.new(0,0,0) tab.Selected = true tab.ZIndex = 3 end function setUnselected(tab) assert(tab) assert(tab:IsA("TextButton")) tab.BackgroundColor3 = Color3.new(0,0,0) tab.TextColor3 = Color3.new(1,1,1) tab.Selected = false tab.ZIndex = 1 end function updateTabGui(selectedTab) assert(selectedTab) if selectedTab == "gear" then elseif selectedTab == "wardrobe" then end end function mouseLeaveTab(button) assert(button) assert(button:IsA("TextButton")) if button.Selected then return end button.BackgroundColor3 = Color3.new(0,0,0) end function mouseOverTab(button) assert(button) assert(button:IsA("TextButton")) if button.Selected then return end button.BackgroundColor3 = Color3.new(39/255,39/255,39/255) end function newTabClicked(tabName) assert(tabName) tabName = string.lower(tabName) currentTab = tabName updateTabGui(tabName) tabClickedEvent:Fire(tabName) resetSearch() end function trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end function splitByWhitespace(text) if type(text) ~= "string" then return nil end local terms = {} for token in string.gmatch(text, "[^%s]+") do if string.len(token) > 0 then table.insert(terms,token) end end return terms end function resetSearchBoxGui() resetButton.Visible = false searchBox.Text = searchDefaultText end function doSearch() local searchText = searchBox.Text if searchText == "" then resetSearch() return end searchText = trim(searchText) resetButton.Visible = true termTable = splitByWhitespace(searchText) searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible end function resetSearch() resetSearchBoxGui() searchRequestedEvent:Fire() end local backpackReady = function() readyForNextEvent = true end --------------------------- End Internal Functions ------------------------------------- ------------------------------ Public Functions Setup ------------------------------------- createPublicFunction("CloseBackpack", hideBackpack) createPublicFunction("BackpackReady", backpackReady) ------------------------------ End Public Functions Setup --------------------------------- ------------------------ Connections/Script Main ------------------------------------------- screen.Changed:connect(function(prop) if prop == "AbsoluteSize" then resizeEvent:Fire(screen.AbsoluteSize) end end) -- GuiService key setup game:GetService("GuiService"):AddKey(tilde) game:GetService("GuiService"):AddKey(backquote) game:GetService("GuiService").KeyPressed:connect(function(key) if not active then return end if key == tilde or key == backquote then toggleBackpack() showBackpack() end end) backpackButton.MouseButton1Click:connect(function() if not active then return end toggleBackpack() end) if game.Players.LocalPlayer["Character"] then activateBackpack() end game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack) -- search functions searchBox.FocusLost:connect(function(enterPressed) if enterPressed or searchBox.Text ~= "" then doSearch() elseif searchBox.Text == "" then resetSearch() end end) searchButton.MouseButton1Click:connect(doSearch) resetButton.MouseButton1Click:connect(resetSearch) --backpackButton.Visible = true false BackpackResizer print("carrot is gay") local t = {} local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc) local eventConnection = nil --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away) local tryConnect = function() if game:IsAncestorOf(parentInstance) then --Entering the world, make sure we are connected/synced if not eventConnection then eventConnection = instance[event]:connect(signalFunc) if syncFunc then syncFunc() end end else --Probably leaving the world, so disconnect for now if eventConnection then eventConnection:disconnect() if removeFunc then removeFunc() end end end end --Hook it up to ancestryChanged signal local connection = parentInstance.AncestryChanged:connect(tryConnect) --Now connect us if we're already in the world tryConnect() return connection end local function getScreenGuiAncestor(instance) local localInstance = instance while localInstance and not localInstance:IsA("ScreenGui") do localInstance = localInstance.Parent end return localInstance end local function CreateButtons(frame, buttons, yPos, ySize) local buttonNum = 1 local buttonObjs = {} for i, obj in ipairs(buttons) do local button = Instance.new("TextButton") button.Name = "Button" .. buttonNum button.Font = Enum.Font.Arial button.FontSize = Enum.FontSize.Size18 button.AutoButtonColor = true button.Modal = true if obj["Style"] then button.Style = obj.Style else button.Style = Enum.ButtonStyle.RobloxButton end if obj["ZIndex"] then button.ZIndex = obj.ZIndex end button.Text = obj.Text button.TextColor3 = Color3.new(1,1,1) button.MouseButton1Click:connect(obj.Function) button.Parent = frame buttonObjs[buttonNum] = button buttonNum = buttonNum + 1 end local numButtons = buttonNum-1 if numButtons == 1 then frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset) elseif numButtons == 2 then frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset) frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset) frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset) elseif numButtons >= 3 then local spacing = .1 / numButtons local buttonSize = .9 / numButtons buttonNum = 1 while buttonNum <= numButtons do buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset) buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset) buttonNum = buttonNum + 1 end end end local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps) local newStep = steps - 1 --otherwise we really get one more step than we want local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X )) local wholeNum, remainder = math.modf(relativePosX * newStep) if remainder > 0.5 then wholeNum = wholeNum + 1 end relativePosX = wholeNum/newStep local result = math.ceil(relativePosX * newStep) if sliderPosition.Value ~= (result + 1) then --only update if we moved a step sliderPosition.Value = result + 1 slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end end local function cancelSlide(areaSoak) areaSoak.Visible = false if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end end t.CreateStyledMessageDialog = function(title, message, style, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0, 165) frame.Position = UDim2.new(0.25, 0, 0.5, -72.5) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local styleImage = Instance.new("ImageLabel") styleImage.Name = "StyleImage" styleImage.BackgroundTransparency = 1 styleImage.Position = UDim2.new(0,5,0,15) if style == "error" or style == "Error" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42565285" elseif style == "notify" or style == "Notify" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42604978" elseif style == "confirm" or style == "Confirm" then styleImage.Size = UDim2.new(0, 74, 0, 76) styleImage.Image = "http://www.roblox.com/asset/?id=42557901" else return t.CreateMessageDialog(title,message,buttons) end styleImage.Parent = frame local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.TextStrokeTransparency = 0 titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 80, 0, 0) titleLabel.Size = UDim2.new(1, -80, 0, 40) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextStrokeTransparency = 0 messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 80, 0, 45) messageLabel.Size = UDim2.new(0.95, -80, 0, 55) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) ) return frame end t.CreateMessageDialog = function(title, message, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0.5, 0) frame.Position = UDim2.new(0.25, 0, 0.25, 0) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 0, 0, 0) titleLabel.Size = UDim2.new(1, 0, 0.15, 0) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0) messageLabel.Size = UDim2.new(0.95, 0, .55, 0) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0)) return frame end t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ) local baseZIndex = 0 if (type(baseZ) == "number") then baseZIndex = baseZ end local width = UDim.new(0, 100) local height = UDim.new(0, 32) local xPos = 0.055 local frame = Instance.new("Frame") local textColor = Color3.new(1,1,1) if (whiteSkin) then textColor = Color3.new(0.5, 0.5, 0.5) end frame.Name = "DropDownMenu" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(width, height) local dropDownMenu = Instance.new("TextButton") dropDownMenu.Name = "DropDownMenuButton" dropDownMenu.TextWrap = true dropDownMenu.TextColor3 = textColor dropDownMenu.Text = "Choose One" dropDownMenu.Font = Enum.Font.ArialBold dropDownMenu.FontSize = Enum.FontSize.Size18 dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center dropDownMenu.BackgroundTransparency = 1 dropDownMenu.AutoButtonColor = true if (whiteSkin) then dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else dropDownMenu.Style = Enum.ButtonStyle.RobloxButton end dropDownMenu.Size = UDim2.new(1,0,1,0) dropDownMenu.Parent = frame dropDownMenu.ZIndex = 2 + baseZIndex local dropDownIcon = Instance.new("ImageLabel") dropDownIcon.Name = "Icon" dropDownIcon.Active = false if (whiteSkin) then dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png" dropDownIcon.Size = UDim2.new(0,16,0,12) dropDownIcon.Position = UDim2.new(1,-17,0.5, -6) else dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894" dropDownIcon.Size = UDim2.new(0,11,0,6) dropDownIcon.Position = UDim2.new(1,-11,0.5, -2) end dropDownIcon.BackgroundTransparency = 1 dropDownIcon.Parent = dropDownMenu dropDownIcon.ZIndex = 2 + baseZIndex local itemCount = #items local dropDownItemCount = #items local useScrollButtons = false if dropDownItemCount > 6 then useScrollButtons = true dropDownItemCount = 6 end local droppedDownMenu = Instance.new("TextButton") droppedDownMenu.Name = "List" droppedDownMenu.Text = "" droppedDownMenu.BackgroundTransparency = 1 --droppedDownMenu.AutoButtonColor = true if (whiteSkin) then droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton end droppedDownMenu.Visible = false droppedDownMenu.Active = true --Blocks clicks droppedDownMenu.Position = UDim2.new(0,0,0,0) droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0) droppedDownMenu.Parent = frame droppedDownMenu.ZIndex = 2 + baseZIndex local choiceButton = Instance.new("TextButton") choiceButton.Name = "ChoiceButton" choiceButton.BackgroundTransparency = 1 choiceButton.BorderSizePixel = 0 choiceButton.Text = "ReplaceMe" choiceButton.TextColor3 = textColor choiceButton.TextXAlignment = Enum.TextXAlignment.Left choiceButton.TextYAlignment = Enum.TextYAlignment.Center choiceButton.BackgroundColor3 = Color3.new(1, 1, 1) choiceButton.Font = Enum.Font.Arial choiceButton.FontSize = Enum.FontSize.Size18 if useScrollButtons then choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0) else choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0) end choiceButton.TextWrap = true choiceButton.ZIndex = 2 + baseZIndex local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = true areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 3 + baseZIndex local dropDownSelected = false local scrollUpButton local scrollDownButton local scrollMouseCount = 0 local setZIndex = function(baseZIndex) droppedDownMenu.ZIndex = baseZIndex +1 if scrollUpButton then scrollUpButton.ZIndex = baseZIndex + 3 end if scrollDownButton then scrollDownButton.ZIndex = baseZIndex + 3 end local children = droppedDownMenu:GetChildren() if children then for i, child in ipairs(children) do if child.Name == "ChoiceButton" then child.ZIndex = baseZIndex + 2 elseif child.Name == "ClickCaptureButton" then child.ZIndex = baseZIndex end end end end local scrollBarPosition = 1 local updateScroll = function() if scrollUpButton then scrollUpButton.Active = scrollBarPosition > 1 end if scrollDownButton then scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount end local children = droppedDownMenu:GetChildren() if not children then return end local childNum = 1 for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then obj.Visible = false else obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0) obj.Visible = true end obj.TextColor3 = textColor obj.BackgroundTransparency = 1 childNum = childNum + 1 end end end local toggleVisibility = function() dropDownSelected = not dropDownSelected areaSoak.Visible = not areaSoak.Visible dropDownMenu.Visible = not dropDownSelected droppedDownMenu.Visible = dropDownSelected if dropDownSelected then setZIndex(4 + baseZIndex) else setZIndex(2 + baseZIndex) end if useScrollButtons then updateScroll() end end droppedDownMenu.MouseButton1Click:connect(toggleVisibility) local updateSelection = function(text) local foundItem = false local children = droppedDownMenu:GetChildren() local childNum = 1 if children then for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if obj.Text == text then obj.Font = Enum.Font.ArialBold foundItem = true scrollBarPosition = childNum if (whiteSkin) then obj.TextColor3 = Color3.new(90/255,142/255,233/255) end else obj.Font = Enum.Font.Arial if (whiteSkin) then obj.TextColor3 = textColor end end childNum = childNum + 1 end end end if not text then dropDownMenu.Text = "Choose One" scrollBarPosition = 1 else if not foundItem then error("Invalid Selection Update -- " .. text) end if scrollBarPosition + dropDownItemCount > itemCount + 1 then scrollBarPosition = itemCount - dropDownItemCount + 1 end dropDownMenu.Text = text end end local function scrollDown() if scrollBarPosition + dropDownItemCount <= itemCount then scrollBarPosition = scrollBarPosition + 1 updateScroll() return true end return false end local function scrollUp() if scrollBarPosition > 1 then scrollBarPosition = scrollBarPosition - 1 updateScroll() return true end return false end if useScrollButtons then --Make some scroll buttons scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0) scrollUpButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollUp() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollUp() == false then break end wait(0.1) end end) scrollUpButton.Parent = droppedDownMenu scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) scrollDownButton.Position = UDim2.new(1,-11,1,-11) scrollDownButton.Parent = droppedDownMenu scrollDownButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollDown() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollDown() == false then break end wait(0.1) end end) local scrollbar = Instance.new("ImageLabel") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4) scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2) scrollbar.Parent = droppedDownMenu end for i,item in ipairs(items) do -- needed to maintain local scope for items in event listeners below local button = choiceButton:clone() if forRoblox then button.RobloxLocked = true end button.Text = item button.Parent = droppedDownMenu if (whiteSkin) then button.TextColor3 = textColor end button.MouseButton1Click:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 updateSelection(item) onSelect(item) toggleVisibility() end) button.MouseEnter:connect(function() --Add Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(0,0,0) end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 end) end --This does the initial layout of the buttons updateScroll() frame.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(frame) end end) dropDownMenu.MouseButton1Click:connect(toggleVisibility) areaSoak.MouseButton1Click:connect(toggleVisibility) return frame, updateSelection end t.CreatePropertyDropDownMenu = function(instance, property, enum) local items = enum:GetEnumItems() local names = {} local nameToItem = {} for i,obj in ipairs(items) do names[i] = obj.Name nameToItem[obj.Name] = obj end local frame local updateSelection frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end) ScopedConnect(frame, instance, "Changed", function(prop) if prop == property then updateSelection(instance[property].Name) end end, function() updateSelection(instance[property].Name) end) return frame end t.GetFontHeight = function(font, fontSize) if font == nil or fontSize == nil then error("Font and FontSize must be non-nil") end if font == Enum.Font.Legacy then if fontSize == Enum.FontSize.Size8 then return 12 elseif fontSize == Enum.FontSize.Size9 then return 14 elseif fontSize == Enum.FontSize.Size10 then return 15 elseif fontSize == Enum.FontSize.Size11 then return 17 elseif fontSize == Enum.FontSize.Size12 then return 18 elseif fontSize == Enum.FontSize.Size14 then return 21 elseif fontSize == Enum.FontSize.Size18 then return 27 elseif fontSize == Enum.FontSize.Size24 then return 36 elseif fontSize == Enum.FontSize.Size36 then return 54 elseif fontSize == Enum.FontSize.Size48 then return 72 else error("Unknown FontSize") end elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then if fontSize == Enum.FontSize.Size8 then return 8 elseif fontSize == Enum.FontSize.Size9 then return 9 elseif fontSize == Enum.FontSize.Size10 then return 10 elseif fontSize == Enum.FontSize.Size11 then return 11 elseif fontSize == Enum.FontSize.Size12 then return 12 elseif fontSize == Enum.FontSize.Size14 then return 14 elseif fontSize == Enum.FontSize.Size18 then return 18 elseif fontSize == Enum.FontSize.Size24 then return 24 elseif fontSize == Enum.FontSize.Size36 then return 36 elseif fontSize == Enum.FontSize.Size48 then return 48 else error("Unknown FontSize") end else error("Unknown Font " .. font) end end local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable) local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y for i, child in ipairs(guiObjects) do if child:IsA("TextLabel") or child:IsA("TextButton") then local isLabel = child:IsA("TextLabel") if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining) if child.TextFits and child.TextBounds.Y < pixelsRemaining then child.Visible = true if isLabel then child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"]) else child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"]) end while not child.TextFits do child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1) end pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end else child.Visible = false pixelsRemaining = -1 end else --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y child.Visible = (pixelsRemaining >= 0) end end end t.LayoutGuiObjects = function(frame, guiObjects, settingsTable) if not frame:IsA("GuiObject") then error("Frame must be a GuiObject") end for i, child in ipairs(guiObjects) do if not child:IsA("GuiObject") then error("All elements that are layed out must be of type GuiObject") end end if not settingsTable then settingsTable = {} end if not settingsTable["TextLabelSizePadY"] then settingsTable["TextLabelSizePadY"] = 0 end if not settingsTable["TextLabelPositionPadY"] then settingsTable["TextLabelPositionPadY"] = 0 end if not settingsTable["TextButtonSizePadY"] then settingsTable["TextButtonSizePadY"] = 12 end if not settingsTable["TextButtonPositionPadY"] then settingsTable["TextButtonPositionPadY"] = 2 end --Wrapper frame takes care of styled objects local wrapperFrame = Instance.new("Frame") wrapperFrame.Name = "WrapperFrame" wrapperFrame.BackgroundTransparency = 1 wrapperFrame.Size = UDim2.new(1,0,1,0) wrapperFrame.Parent = frame for i, child in ipairs(guiObjects) do child.Parent = wrapperFrame end local recalculate = function() wait() layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(recalculate) layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end t.CreateSlider = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 4 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local bar = Instance.new("TextButton") bar.Text = "" bar.AutoButtonColor = false bar.Name = "Bar" bar.BackgroundColor3 = Color3.new(0,0,0) if type(width) == "number" then bar.Size = UDim2.new(0,width,0,5) else bar.Size = UDim2.new(0,200,0,5) end bar.BorderColor3 = Color3.new(95/255,95/255,95/255) bar.ZIndex = 2 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/Slider.png" slider.Position = UDim2.new(0,0,0.5,-10) slider.Size = UDim2.new(0,20,0,20) slider.ZIndex = 3 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (steps - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateSliderNew = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 6 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local sliderBarImgHeight = 7 local sliderBarCapImgWidth = 4 local bar = Instance.new("ImageButton") bar.BackgroundTransparency = 1 bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png" bar.Name = "Bar" local displayWidth = 200 if type(width) == "number" then bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight) displayWidth = width - (sliderBarCapImgWidth * 2) else bar.Size = UDim2.new(0,200,0,sliderBarImgHeight) end bar.ZIndex = 3 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local barLeft = bar:clone() barLeft.Name = "BarLeft" barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png" barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight) barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset) barLeft.Parent = sliderGui barLeft.ZIndex = 3 local barRight = barLeft:clone() barRight.Name = "BarRight" barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png" barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset) barRight.Parent = sliderGui local fillLeft = barLeft:clone() fillLeft.Name = "FillLeft" fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png" fillLeft.Parent = sliderGui fillLeft.ZIndex = 4 local fill = fillLeft:clone() fill.Name = "Fill" fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png" fill.Parent = bar fill.ZIndex = 4 fill.Position = UDim2.new(0, 0, 0, 0) fill.Size = UDim2.new(0.5, 0, 1, 0) -- bar.Visible = false local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/slider_new_tab.png" slider.Position = UDim2.new(0,0,0.5,-14) slider.Size = UDim2.new(0,28,0,28) slider.ZIndex = 5 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (steps - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) fill.Size = UDim2.new(relativePosX, 0, 1, 0) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateTrueScrollingFrame = function() local lowY = nil local highY = nil local dragCon = nil local upCon = nil local internalChange = false local descendantsChangeConMap = {} local scrollingFrame = Instance.new("Frame") scrollingFrame.Name = "ScrollingFrame" scrollingFrame.Active = true scrollingFrame.Size = UDim2.new(1,0,1,0) scrollingFrame.ClipsDescendants = true local controlFrame = Instance.new("Frame") controlFrame.Name = "ControlFrame" controlFrame.BackgroundTransparency = 1 controlFrame.Size = UDim2.new(0,18,1,0) controlFrame.Position = UDim2.new(1,-20,0,0) controlFrame.Parent = scrollingFrame local scrollBottom = Instance.new("BoolValue") scrollBottom.Value = false scrollBottom.Name = "ScrollBottom" scrollBottom.Parent = controlFrame local scrollUp = Instance.new("BoolValue") scrollUp.Value = false scrollUp.Name = "scrollUp" scrollUp.Parent = controlFrame local scrollUpButton = Instance.new("TextButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.Text = "" scrollUpButton.AutoButtonColor = false scrollUpButton.BackgroundColor3 = Color3.new(0,0,0) scrollUpButton.BorderColor3 = Color3.new(1,1,1) scrollUpButton.BackgroundTransparency = 0.5 scrollUpButton.Size = UDim2.new(0,18,0,18) scrollUpButton.ZIndex = 2 scrollUpButton.Parent = controlFrame for i = 1, 6 do local triFrame = Instance.new("Frame") triFrame.BorderColor3 = Color3.new(1,1,1) triFrame.Name = "tri" .. tostring(i) triFrame.ZIndex = 3 triFrame.BackgroundTransparency = 0.5 triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0) triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1)) triFrame.Parent = scrollUpButton end scrollUpButton.MouseEnter:connect(function() scrollUpButton.BackgroundTransparency = 0.1 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.1 end end) scrollUpButton.MouseLeave:connect(function() scrollUpButton.BackgroundTransparency = 0.5 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.5 end end) local scrollDownButton = scrollUpButton:clone() scrollDownButton.Name = "ScrollDownButton" scrollDownButton.Position = UDim2.new(0,0,1,-18) local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1)) end scrollDownButton.MouseEnter:connect(function() scrollDownButton.BackgroundTransparency = 0.1 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.1 end end) scrollDownButton.MouseLeave:connect(function() scrollDownButton.BackgroundTransparency = 0.5 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.5 end end) scrollDownButton.Parent = controlFrame local scrollTrack = Instance.new("Frame") scrollTrack.Name = "ScrollTrack" scrollTrack.BackgroundTransparency = 1 scrollTrack.Size = UDim2.new(0,18,1,-38) scrollTrack.Position = UDim2.new(0,0,0,19) scrollTrack.Parent = controlFrame local scrollbar = Instance.new("TextButton") scrollbar.BackgroundColor3 = Color3.new(0,0,0) scrollbar.BorderColor3 = Color3.new(1,1,1) scrollbar.BackgroundTransparency = 0.5 scrollbar.AutoButtonColor = false scrollbar.Text = "" scrollbar.Active = true scrollbar.Name = "ScrollBar" scrollbar.ZIndex = 2 scrollbar.BackgroundTransparency = 0.5 scrollbar.Size = UDim2.new(0, 18, 0.1, 0) scrollbar.Position = UDim2.new(0,0,0,0) scrollbar.Parent = scrollTrack local scrollNub = Instance.new("Frame") scrollNub.Name = "ScrollNub" scrollNub.BorderColor3 = Color3.new(1,1,1) scrollNub.Size = UDim2.new(0,10,0,0) scrollNub.Position = UDim2.new(0.5,-5,0.5,0) scrollNub.ZIndex = 2 scrollNub.BackgroundTransparency = 0.5 scrollNub.Parent = scrollbar local newNub = scrollNub:clone() newNub.Position = UDim2.new(0.5,-5,0.5,-2) newNub.Parent = scrollbar local lastNub = scrollNub:clone() lastNub.Position = UDim2.new(0.5,-5,0.5,2) lastNub.Parent = scrollbar scrollbar.MouseEnter:connect(function() scrollbar.BackgroundTransparency = 0.1 scrollNub.BackgroundTransparency = 0.1 newNub.BackgroundTransparency = 0.1 lastNub.BackgroundTransparency = 0.1 end) scrollbar.MouseLeave:connect(function() scrollbar.BackgroundTransparency = 0.5 scrollNub.BackgroundTransparency = 0.5 newNub.BackgroundTransparency = 0.5 lastNub.BackgroundTransparency = 0.5 end) local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local function positionScrollBar(x,y,offset) local oldPos = scrollbar.Position if y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) return (oldPos ~= scrollbar.Position) end local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) return (oldPos ~= scrollbar.Position) end local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y if newScaleYPos + relativeSize > 1 then newScaleYPos = 1 - relativeSize scrollBottom.Value = true scrollUp.Value = false elseif newScaleYPos <= 0 then newScaleYPos = 0 scrollUp.Value = true scrollBottom.Value = false else scrollUp.Value = false scrollBottom.Value = false end scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0) return (oldPos ~= scrollbar.Position) end local function drillDownSetHighLow(instance) if not instance or not instance:IsA("GuiObject") then return end if instance == controlFrame then return end if instance:IsDescendantOf(controlFrame) then return end if not instance.Visible then return end if lowY and lowY > instance.AbsolutePosition.Y then lowY = instance.AbsolutePosition.Y elseif not lowY then lowY = instance.AbsolutePosition.Y end if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end local children = instance:GetChildren() for i = 1, #children do drillDownSetHighLow(children[i]) end end local function resetHighLow() local firstChildren = scrollingFrame:GetChildren() for i = 1, #firstChildren do drillDownSetHighLow(firstChildren[i]) end end local function recalculate() internalChange = true local percentFrame = 0 if scrollbar.Position.Y.Scale > 0 then if scrollbar.Visible then percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y) else percentFrame = 0 end end if percentFrame > 0.99 then percentFrame = 1 end local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame local guiChildren = scrollingFrame:GetChildren() for i = 1, #guiChildren do if guiChildren[i] ~= controlFrame then guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset, 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount) end end lowY = nil highY = nil resetHighLow() internalChange = false end local function setSliderSizeAndPosition() if not highY or not lowY then return end local totalYSpan = math.abs(highY - lowY) if totalYSpan == 0 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end return end local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan if percentShown >= 1 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false recalculate() else scrollbar.Visible = true scrollDownButton.Visible = true scrollUpButton.Visible = true scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0) end local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2) if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) end if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) end end local buttonScrollAmountPixels = 7 local reentrancyGuardScrollUp = false local function doScrollUp() if reentrancyGuardScrollUp then return end reentrancyGuardScrollUp = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollUp = false end local reentrancyGuardScrollDown = false local function doScrollDown() if reentrancyGuardScrollDown then return end reentrancyGuardScrollDown = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollDown = false end local function scrollUp(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local function scrollDown(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end scrollbar.MouseButton1Down:connect(function(x,y) if scrollbar.Active then scrollStamp = tick() local mouseOffset = y - scrollbar.AbsolutePosition.y if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end local prevY = y local reentrancyGuardMouseScroll = false dragCon = mouseDrag.MouseMoved:connect(function(x,y) if reentrancyGuardMouseScroll then return end reentrancyGuardMouseScroll = true if positionScrollBar(x,y,mouseOffset) then recalculate() end reentrancyGuardMouseScroll = false end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect(function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect(function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) local function heightCheck(instance) if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end setSliderSizeAndPosition() end local function highLowRecheck() local oldLowY = lowY local oldHighY = highY lowY = nil highY = nil resetHighLow() if (lowY ~= oldLowY) or (highY ~= oldHighY) then setSliderSizeAndPosition() end end local function descendantChanged(this, prop) if internalChange then return end if not this.Visible then return end if prop == "Size" or prop == "Position" then wait() highLowRecheck() end end scrollingFrame.DescendantAdded:connect(function(instance) if not instance:IsA("GuiObject") then return end if instance.Visible then wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end) end) scrollingFrame.DescendantRemoving:connect(function(instance) if not instance:IsA("GuiObject") then return end if descendantsChangeConMap[instance] then descendantsChangeConMap[instance]:disconnect() descendantsChangeConMap[instance] = nil end wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end) scrollingFrame.Changed:connect(function(prop) if prop == "AbsoluteSize" then if not highY or not lowY then return end highLowRecheck() setSliderSizeAndPosition() end end) return scrollingFrame, controlFrame end t.CreateScrollingFrame = function(orderList,scrollStyle) local frame = Instance.new("Frame") frame.Name = "ScrollingFrame" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1,0,1,0) local scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) local scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) local scrollbar = Instance.new("ImageButton") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, 0, 150) local scrollStamp = 0 local scrollDrag = Instance.new("ImageButton") scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186" scrollDrag.Size = UDim2.new(1, 0, 0, 16) scrollDrag.BackgroundTransparency = 1 scrollDrag.Name = "ScrollDrag" scrollDrag.Active = true scrollDrag.Parent = scrollbar local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local style = "simple" if scrollStyle and tostring(scrollStyle) then style = scrollStyle end local scrollPosition = 1 local rowSize = 0 local howManyDisplayed = 0 local layoutGridScrollBar = function() howManyDisplayed = 0 local guiObjects = {} if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end if scrollPosition < 1 then scrollPosition = 1 end local totalPixelsY = frame.AbsoluteSize.Y local pixelsRemainingY = frame.AbsoluteSize.Y local totalPixelsX = frame.AbsoluteSize.X local xCounter = 0 local rowSizeCounter = 0 local setRowSize = true local pixelsBelowScrollbar = 0 local pos = #guiObjects local currentRowY = 0 pos = scrollPosition --count up from current scroll position to fill out grid while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X --previous pos was the end of a row if xCounter >= totalPixelsX then pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 xCounter = guiObjects[pos].AbsoluteSize.X end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos + 1 end --Count wherever current row left off pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 pos = scrollPosition - 1 xCounter = 0 --objects with varying X,Y dimensions can rarely cause minor errors --rechecking every new scrollPosition is necessary to avoid 100% of errors --count backwards from current scrollPosition to see if we can add more rows while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X rowSizeCounter = rowSizeCounter + 1 if xCounter >= totalPixelsX then rowSize = rowSizeCounter - 1 rowSizeCounter = 0 xCounter = guiObjects[pos].AbsoluteSize.X if pixelsBelowScrollbar + currentRowY <= totalPixelsY then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY if scrollPosition <= rowSize then scrollPosition = 1 break else scrollPosition = scrollPosition - rowSize end currentRowY = 0 else break end end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos - 1 end --Do check last time if pos = 0 if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then scrollPosition = 1 end xCounter = 0 --pos = scrollPosition rowSizeCounter = 0 setRowSize = true local lastChildSize = 0 local xOffset,yOffset = 0 if guiObjects[1] then yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2) xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2) end for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemainingY < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject if setRowSize then rowSizeCounter = rowSizeCounter + 1 end if xCounter + child.AbsoluteSize.X >= totalPixelsX then if setRowSize then rowSize = rowSizeCounter - 1 setRowSize = false end xCounter = 0 pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y end child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset) xCounter = xCounter + child.AbsoluteSize.X child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0) if child.Visible then howManyDisplayed = howManyDisplayed + 1 end lastChildSize = child.AbsoluteSize end end end scrollUpButton.Active = (scrollPosition > 1) if lastChildSize == 0 then scrollDownButton.Active = false else scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0) end scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local layoutSimpleScrollBar = function() local guiObjects = {} howManyDisplayed = 0 if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y local pixelsBelowScrollbar = 0 local pos = #guiObjects while pixelsBelowScrollbar < totalPixels and pos >= 1 do if pos >= scrollPosition then pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y else if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y if scrollPosition <= 1 then scrollPosition = 1 break else --local ("Backing up ScrollPosition from -- " ..scrollPosition) scrollPosition = scrollPosition - 1 end else break end end pos = pos - 1 end pos = scrollPosition for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemaining < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if (pixelsRemaining >= 0) then child.Visible = true howManyDisplayed = howManyDisplayed + 1 else child.Visible = false end end end end scrollUpButton.Active = (scrollPosition > 1) scrollDownButton.Active = (pixelsRemaining < 0) scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local moveDragger = function() local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end if not scrollDrag.Parent then return end local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1)) if dragSizeY < 16 then dragSizeY = 16 end scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY) local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed)) if relativeYPos > 1 then relativeYPos = 1 elseif relativeYPos < 0 then relativeYPos = 0 end local absYPos = 0 if relativeYPos ~= 0 then absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y) end scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos) end local reentrancyGuard = false local recalculate = function() if reentrancyGuard then return end reentrancyGuard = true wait() local success, err = nil if style == "grid" then success, err = pcall(function() layoutGridScrollBar() end) elseif style == "simple" then success, err = pcall(function() layoutSimpleScrollBar() end) end if not success then print(err) end moveDragger() reentrancyGuard = false end local doScrollUp = function() scrollPosition = (scrollPosition) - rowSize if scrollPosition < 1 then scrollPosition = 1 end recalculate(nil) end local doScrollDown = function() scrollPosition = (scrollPosition) + rowSize recalculate(nil) end local scrollUp = function(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local scrollDown = function(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local y = 0 scrollDrag.MouseButton1Down:connect(function(x,y) if scrollDrag.Active then scrollStamp = tick() local mouseOffset = y - scrollDrag.AbsolutePosition.y local dragCon local upCon dragCon = mouseDrag.MouseMoved:connect(function(x,y) local barAbsPos = scrollbar.AbsolutePosition.y local barAbsSize = scrollbar.AbsoluteSize.y local dragAbsSize = scrollDrag.AbsoluteSize.y local barAbsOne = barAbsPos + barAbsSize - dragAbsSize y = y - mouseOffset y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y y = y - barAbsPos local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end local doublePercent = y/(barAbsSize-dragAbsSize) local rowDiff = rowSize local totalScrollCount = guiObjects - (howManyDisplayed - 1) local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff if newScrollPosition < scrollPosition then rowDiff = -rowDiff end if newScrollPosition < 1 then newScrollPosition = 1 end scrollPosition = newScrollPosition recalculate(nil) end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect( function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect( function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollbar.MouseButton1Down:connect( function(x,y) if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then scrollDown(y) elseif y < (scrollDrag.AbsolutePosition.y) then scrollUp(y) end end) frame.ChildAdded:connect(function() recalculate(nil) end) frame.ChildRemoved:connect(function() recalculate(nil) end) frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(function() recalculate(nil) end) return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar end local function binaryGrow(min, max, fits) if min > max then return min end local biggestLegal = min while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then biggestLegal = mid --Try growing min = mid + 1 else --Doesn't fit, shrink max = mid - 1 end end return biggestLegal end local function binaryShrink(min, max, fits) if min > max then return min end local smallestLegal = max while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then smallestLegal = mid --It fits, shrink max = mid - 1 else --Doesn't fit, grow min = mid + 1 end end return smallestLegal end local function getGuiOwner(instance) while instance ~= nil do if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then return instance end instance = instance.Parent end return nil end t.AutoTruncateTextObject = function(textLabel) local text = textLabel.Text local fullLabel = textLabel:Clone() fullLabel.Name = "Full" .. textLabel.Name fullLabel.BorderSizePixel = 0 fullLabel.BackgroundTransparency = 0 fullLabel.Text = text fullLabel.TextXAlignment = Enum.TextXAlignment.Center fullLabel.Position = UDim2.new(0,-3,0,0) fullLabel.Size = UDim2.new(0,100,1,0) fullLabel.Visible = false fullLabel.Parent = textLabel local shortText = nil local mouseEnterConnection = nil local mouseLeaveConnection= nil local checkForResize = function() if getGuiOwner(textLabel) == nil then return end textLabel.Text = text if textLabel.TextFits then --Tear down the rollover if it is active if mouseEnterConnection then mouseEnterConnection:disconnect() mouseEnterConnection = nil end if mouseLeaveConnection then mouseLeaveConnection:disconnect() mouseLeaveConnection = nil end else local len = string.len(text) textLabel.Text = text .. "~" --Shrink the text local textSize = binaryGrow(0, len, function(pos) if pos == 0 then textLabel.Text = "~" else textLabel.Text = string.sub(text, 1, pos) .. "~" end return textLabel.TextFits end) shortText = string.sub(text, 1, textSize) .. "~" textLabel.Text = shortText --Make sure the fullLabel fits if not fullLabel.TextFits then --Already too small, grow it really bit to start fullLabel.Size = UDim2.new(0, 10000, 1, 0) end --Okay, now try to binary shrink it back down local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X, function(size) fullLabel.Size = UDim2.new(0, size, 1, 0) return fullLabel.TextFits end) fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0) --Now setup the rollover effects, if they are currently off if mouseEnterConnection == nil then mouseEnterConnection = textLabel.MouseEnter:connect( function() fullLabel.ZIndex = textLabel.ZIndex + 1 fullLabel.Visible = true --textLabel.Text = "" end) end if mouseLeaveConnection == nil then mouseLeaveConnection = textLabel.MouseLeave:connect( function() fullLabel.Visible = false --textLabel.Text = shortText end) end end end textLabel.AncestryChanged:connect(checkForResize) textLabel.Changed:connect( function(prop) if prop == "AbsoluteSize" then checkForResize() end end) checkForResize() local function changeText(newText) text = newText fullLabel.Text = text checkForResize() end return textLabel, changeText end local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue) if fromPage then fromPage.Visible = false if transitionFrame.Visible == false then transitionFrame.Size = fromPage.Size transitionFrame.Position = fromPage.Position end else if transitionFrame.Visible == false then transitionFrame.Size = UDim2.new(0.0,50,0.0,50) transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25) end end transitionFrame.Visible = true currentPageValue.Value = nil local newsize, newPosition if toPage then --Make it visible so it resizes toPage.Visible = true newSize = toPage.Size newPosition = toPage.Position toPage.Visible = false else newSize = UDim2.new(0.0,50,0.0,50) newPosition = UDim2.new(0.5,-25,0.5,-25) end transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true, function(state) if state == Enum.TweenStatus.Completed then transitionFrame.Visible = false if toPage then toPage.Visible = true currentPageValue.Value = toPage end end end) end t.CreateTutorial = function(name, tutorialKey, createButtons) local frame = Instance.new("Frame") frame.Name = "Tutorial-" .. name frame.BackgroundTransparency = 1 frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) local transitionFrame = Instance.new("Frame") transitionFrame.Name = "TransitionFrame" transitionFrame.Style = Enum.FrameStyle.RobloxRound transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0) transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0) transitionFrame.Visible = false transitionFrame.Parent = frame local currentPageValue = Instance.new("ObjectValue") currentPageValue.Name = "CurrentTutorialPage" currentPageValue.Value = nil currentPageValue.Parent = frame local boolValue = Instance.new("BoolValue") boolValue.Name = "Buttons" boolValue.Value = createButtons boolValue.Parent = frame local pages = Instance.new("Frame") pages.Name = "Pages" pages.BackgroundTransparency = 1 pages.Size = UDim2.new(1,0,1,0) pages.Parent = frame local function getVisiblePageAndHideOthers() local visiblePage = nil local children = pages:GetChildren() if children then for i,child in ipairs(children) do if child.Visible then if visiblePage then child.Visible = false else visiblePage = child end end end end return visiblePage end local showTutorial = function(alwaysShow) if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then print("Showing tutorial-",tutorialKey) local currentTutorialPage = getVisiblePageAndHideOthers() local firstPage = pages:FindFirstChild("TutorialPage1") if firstPage then TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue) else error("Could not find TutorialPage1") end end end local dismissTutorial = function() local currentTutorialPage = getVisiblePageAndHideOthers() if currentTutorialPage then TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue) end UserSettings().GameSettings:SetTutorialState(tutorialKey, true) end local gotoPage = function(pageNum) local page = pages:FindFirstChild("TutorialPage" .. pageNum) local currentTutorialPage = getVisiblePageAndHideOthers() TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue) end return frame, showTutorial, dismissTutorial, gotoPage end local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton) local frame = Instance.new("Frame") frame.Name = "TutorialPage" frame.Style = Enum.FrameStyle.RobloxRound frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) frame.Visible = false local frameHeader = Instance.new("TextLabel") frameHeader.Name = "Header" frameHeader.Text = name frameHeader.BackgroundTransparency = 1 frameHeader.FontSize = Enum.FontSize.Size24 frameHeader.Font = Enum.Font.ArialBold frameHeader.TextColor3 = Color3.new(1,1,1) frameHeader.TextXAlignment = Enum.TextXAlignment.Center frameHeader.TextWrap = true frameHeader.Size = UDim2.new(1,-55, 0, 22) frameHeader.Position = UDim2.new(0,0,0,0) frameHeader.Parent = frame local skipButton = Instance.new("ImageButton") skipButton.Name = "SkipButton" skipButton.AutoButtonColor = false skipButton.BackgroundTransparency = 1 skipButton.Image = "rbxasset://textures/ui/closeButton.png" skipButton.MouseButton1Click:connect(function() skipTutorial() end) skipButton.MouseEnter:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png" end) skipButton.MouseLeave:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton.png" end) skipButton.Size = UDim2.new(0, 25, 0, 25) skipButton.Position = UDim2.new(1, -25, 0, 0) skipButton.Parent = frame if giveDoneButton then local doneButton = Instance.new("TextButton") doneButton.Name = "DoneButton" doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault doneButton.Text = "Done" doneButton.TextColor3 = Color3.new(1,1,1) doneButton.Font = Enum.Font.ArialBold doneButton.FontSize = Enum.FontSize.Size18 doneButton.Size = UDim2.new(0,100,0,50) doneButton.Position = UDim2.new(0.5,-50,1,-50) if skipTutorial then doneButton.MouseButton1Click:connect(function() skipTutorial() end) end doneButton.Parent = frame end local innerFrame = Instance.new("Frame") innerFrame.Name = "ContentFrame" innerFrame.BackgroundTransparency = 1 innerFrame.Position = UDim2.new(0,0,0,25) innerFrame.Parent = frame local nextButton = Instance.new("TextButton") nextButton.Name = "NextButton" nextButton.Text = "Next" nextButton.TextColor3 = Color3.new(1,1,1) nextButton.Font = Enum.Font.Arial nextButton.FontSize = Enum.FontSize.Size18 nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault nextButton.Size = UDim2.new(0,80, 0, 32) nextButton.Position = UDim2.new(0.5, 5, 1, -32) nextButton.Active = false nextButton.Visible = false nextButton.Parent = frame local prevButton = Instance.new("TextButton") prevButton.Name = "PrevButton" prevButton.Text = "Previous" prevButton.TextColor3 = Color3.new(1,1,1) prevButton.Font = Enum.Font.Arial prevButton.FontSize = Enum.FontSize.Size18 prevButton.Style = Enum.ButtonStyle.RobloxButton prevButton.Size = UDim2.new(0,80, 0, 32) prevButton.Position = UDim2.new(0.5, -85, 1, -32) prevButton.Active = false prevButton.Visible = false prevButton.Parent = frame if giveDoneButton then innerFrame.Size = UDim2.new(1,0,1,-75) else innerFrame.Size = UDim2.new(1,0,1,-22) end local parentConnection = nil local function basicHandleResize() if frame.Visible and frame.Parent then local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y) handleResize(200,maxSize) end end frame.Changed:connect( function(prop) if prop == "Parent" then if parentConnection ~= nil then parentConnection:disconnect() parentConnection = nil end if frame.Parent and frame.Parent:IsA("GuiObject") then parentConnection = frame.Parent.Changed:connect( function(parentProp) if parentProp == "AbsoluteSize" then wait() basicHandleResize() end end) basicHandleResize() end end if prop == "Visible" then basicHandleResize() end end) return frame, innerFrame end t.CreateTextTutorialPage = function(name, text, skipTutorialFunc) local frame = nil local contentFrame = nil local textLabel = Instance.new("TextLabel") textLabel.BackgroundTransparency = 1 textLabel.TextColor3 = Color3.new(1,1,1) textLabel.Text = text textLabel.TextWrap = true textLabel.TextXAlignment = Enum.TextXAlignment.Left textLabel.TextYAlignment = Enum.TextYAlignment.Center textLabel.Font = Enum.Font.Arial textLabel.FontSize = Enum.FontSize.Size14 textLabel.Size = UDim2.new(1,0,1,0) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) frame.Size = UDim2.new(0, size, 0, size) return textLabel.TextFits end) frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc) textLabel.Parent = contentFrame return frame end t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton) local frame = nil local contentFrame = nil local imageLabel = Instance.new("ImageLabel") imageLabel.BackgroundTransparency = 1 imageLabel.Image = imageAsset imageLabel.Size = UDim2.new(0,x,0,y) imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) return size >= x and size >= y end) if size >= x and size >= y then imageLabel.Size = UDim2.new(0,x, 0,y) imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2) else if x > y then --X is limiter, so imageLabel.Size = UDim2.new(1,0,y/x,0) imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0) else --Y is limiter imageLabel.Size = UDim2.new(x/y,0,1, 0) imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0) end end size = size + 50 frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton) imageLabel.Parent = contentFrame return frame end t.AddTutorialPage = function(tutorial, tutorialPage) local transitionFrame = tutorial.TransitionFrame local currentPageValue = tutorial.CurrentTutorialPage if not tutorial.Buttons.Value then tutorialPage.NextButton.Parent = nil tutorialPage.PrevButton.Parent = nil end local children = tutorial.Pages:GetChildren() if children and #children > 0 then tutorialPage.Name = "TutorialPage" .. (#children+1) local previousPage = children[#children] if not previousPage:IsA("GuiObject") then error("All elements under Pages must be GuiObjects") end if tutorial.Buttons.Value then if previousPage.NextButton.Active then error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function") end previousPage.NextButton.MouseButton1Click:connect( function() TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue) end) previousPage.NextButton.Active = true previousPage.NextButton.Visible = true if tutorialPage.PrevButton.Active then error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function") end tutorialPage.PrevButton.MouseButton1Click:connect( function() TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue) end) tutorialPage.PrevButton.Active = true tutorialPage.PrevButton.Visible = true end tutorialPage.Parent = tutorial.Pages else --First child tutorialPage.Name = "TutorialPage1" tutorialPage.Parent = tutorial.Pages end end t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId) if not userIdsForSets then error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids") end if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata") end if not objectSelected then error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!") end if type(objectSelected) ~= "function" then error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!") end if dialogClosed and type(dialogClosed) ~= "function" then error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!") end if showAdminCategories == nil then -- by default, don't show beta sets showAdminCategories = false end local arrayPosition = 1 local insertButtons = {} local insertButtonCons = {} local contents = nil local setGui = nil -- used for water selections local waterForceDirection = "NegX" local waterForce = "None" local waterGui, waterTypeChangedEvent = nil local Data = {} Data.CurrentCategory = nil Data.Category = {} local SetCache = {} local userCategoryButtons = nil local buttonWidth = 64 local buttonHeight = buttonWidth local SmallThumbnailUrl = nil local LargeThumbnailUrl = nil local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower() if useAssetVersionId then LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid=" else LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid=" end local function drillDownSetZIndex(parent, index) local children = parent:GetChildren() for i = 1, #children do if children[i]:IsA("GuiObject") then children[i].ZIndex = index end drillDownSetZIndex(children[i], index) end end -- for terrain stamping local currTerrainDropDownFrame = nil local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"} local terrainShapeMap = {} for i = 1, #terrainShapes do terrainShapeMap[terrainShapes[i]] = i - 1 end terrainShapeMap[terrainShapes[#terrainShapes]] = 6 local function createWaterGui() local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"} local waterForces = {"None", "Small", "Medium", "Strong", "Max"} local waterFrame = Instance.new("Frame") waterFrame.Name = "WaterFrame" waterFrame.Style = Enum.FrameStyle.RobloxSquare waterFrame.Size = UDim2.new(0,150,0,110) waterFrame.Visible = false local waterForceLabel = Instance.new("TextLabel") waterForceLabel.Name = "WaterForceLabel" waterForceLabel.BackgroundTransparency = 1 waterForceLabel.Size = UDim2.new(1,0,0,12) waterForceLabel.Font = Enum.Font.ArialBold waterForceLabel.FontSize = Enum.FontSize.Size12 waterForceLabel.TextColor3 = Color3.new(1,1,1) waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left waterForceLabel.Text = "Water Force" waterForceLabel.Parent = waterFrame local waterForceDirLabel = waterForceLabel:Clone() waterForceDirLabel.Name = "WaterForceDirectionLabel" waterForceDirLabel.Text = "Water Force Direction" waterForceDirLabel.Position = UDim2.new(0,0,0,50) waterForceDirLabel.Parent = waterFrame local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame) waterTypeChangedEvent.Name = "WaterTypeChangedEvent" local waterForceDirectionSelectedFunc = function(newForceDirection) waterForceDirection = newForceDirection waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceSelectedFunc = function(newForce) waterForce = newForce waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc) waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25) waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3) forceWaterDirectionSelection("NegX") waterForceDirectionDropDown.Parent = waterForceDirLabel local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc) forceWaterForceSelection("None") waterForceDropDown.Size = UDim2.new(1,0,0,25) waterForceDropDown.Position = UDim2.new(0,0,1,3) waterForceDropDown.Parent = waterForceLabel return waterFrame, waterTypeChangedEvent end -- Helper Function that contructs gui elements local function createSetGui() local setGui = Instance.new("ScreenGui") setGui.Name = "SetGui" local setPanel = Instance.new("Frame") setPanel.Name = "SetPanel" setPanel.Active = true setPanel.BackgroundTransparency = 1 if position then setPanel.Position = position else setPanel.Position = UDim2.new(0.2, 29, 0.1, 24) end if size then setPanel.Size = size else setPanel.Size = UDim2.new(0.6, -58, 0.64, 0) end setPanel.Style = Enum.FrameStyle.RobloxRound setPanel.ZIndex = 6 setPanel.Parent = setGui -- Children of SetPanel local itemPreview = Instance.new("Frame") itemPreview.Name = "ItemPreview" itemPreview.BackgroundTransparency = 1 itemPreview.Position = UDim2.new(0.8,5,0.085,0) itemPreview.Size = UDim2.new(0.21,0,0.9,0) itemPreview.ZIndex = 6 itemPreview.Parent = setPanel -- Children of ItemPreview local textPanel = Instance.new("Frame") textPanel.Name = "TextPanel" textPanel.BackgroundTransparency = 1 textPanel.Position = UDim2.new(0,0,0.45,0) textPanel.Size = UDim2.new(1,0,0.55,0) textPanel.ZIndex = 6 textPanel.Parent = itemPreview -- Children of TextPanel local rolloverText = Instance.new("TextLabel") rolloverText.Name = "RolloverText" rolloverText.BackgroundTransparency = 1 rolloverText.Size = UDim2.new(1,0,0,48) rolloverText.ZIndex = 6 rolloverText.Font = Enum.Font.ArialBold rolloverText.FontSize = Enum.FontSize.Size24 rolloverText.Text = "" rolloverText.TextColor3 = Color3.new(1,1,1) rolloverText.TextWrap = true rolloverText.TextXAlignment = Enum.TextXAlignment.Left rolloverText.TextYAlignment = Enum.TextYAlignment.Top rolloverText.Parent = textPanel local largePreview = Instance.new("ImageLabel") largePreview.Name = "LargePreview" largePreview.BackgroundTransparency = 1 largePreview.Image = "" largePreview.Size = UDim2.new(1,0,0,170) largePreview.ZIndex = 6 largePreview.Parent = itemPreview local sets = Instance.new("Frame") sets.Name = "Sets" sets.BackgroundTransparency = 1 sets.Position = UDim2.new(0,0,0,5) sets.Size = UDim2.new(0.23,0,1,-5) sets.ZIndex = 6 sets.Parent = setPanel -- Children of Sets local line = Instance.new("Frame") line.Name = "Line" line.BackgroundColor3 = Color3.new(1,1,1) line.BackgroundTransparency = 0.7 line.BorderSizePixel = 0 line.Position = UDim2.new(1,-3,0.06,0) line.Size = UDim2.new(0,3,0.9,0) line.ZIndex = 6 line.Parent = sets local setsLists, controlFrame = t.CreateTrueScrollingFrame() setsLists.Size = UDim2.new(1,-6,0.94,0) setsLists.Position = UDim2.new(0,0,0.06,0) setsLists.BackgroundTransparency = 1 setsLists.Name = "SetsLists" setsLists.ZIndex = 6 setsLists.Parent = sets drillDownSetZIndex(controlFrame, 7) local setsHeader = Instance.new("TextLabel") setsHeader.Name = "SetsHeader" setsHeader.BackgroundTransparency = 1 setsHeader.Size = UDim2.new(0,47,0,24) setsHeader.ZIndex = 6 setsHeader.Font = Enum.Font.ArialBold setsHeader.FontSize = Enum.FontSize.Size24 setsHeader.Text = "Sets" setsHeader.TextColor3 = Color3.new(1,1,1) setsHeader.TextXAlignment = Enum.TextXAlignment.Left setsHeader.TextYAlignment = Enum.TextYAlignment.Top setsHeader.Parent = sets local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(1,-32,0,-2) cancelButton.Size = UDim2.new(0,34,0,34) cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault cancelButton.ZIndex = 6 cancelButton.Text = "" cancelButton.Modal = true cancelButton.Parent = setPanel -- Children of Cancel Button local cancelImage = Instance.new("ImageLabel") cancelImage.Name = "CancelImage" cancelImage.BackgroundTransparency = 1 cancelImage.Image = "http://www.roblox.com/asset/?id=54135717" cancelImage.Position = UDim2.new(0,-2,0,-2) cancelImage.Size = UDim2.new(0,16,0,16) cancelImage.ZIndex = 6 cancelImage.Parent = cancelButton return setGui end local function createSetButton(text) local setButton = Instance.new("TextButton") if text then setButton.Text = text else setButton.Text = "" end setButton.AutoButtonColor = false setButton.BackgroundTransparency = 1 setButton.BackgroundColor3 = Color3.new(1,1,1) setButton.BorderSizePixel = 0 setButton.Size = UDim2.new(1,-5,0,18) setButton.ZIndex = 6 setButton.Visible = false setButton.Font = Enum.Font.Arial setButton.FontSize = Enum.FontSize.Size18 setButton.TextColor3 = Color3.new(1,1,1) setButton.TextXAlignment = Enum.TextXAlignment.Left return setButton end local function buildSetButton(name, setId, setImageId, i, count) local button = createSetButton(name) button.Text = name button.Name = "SetButton" button.Visible = true local setValue = Instance.new("IntValue") setValue.Name = "SetId" setValue.Value = setId setValue.Parent = button local setName = Instance.new("StringValue") setName.Name = "SetName" setName.Value = name setName.Parent = button return button end local function processCategory(sets) local setButtons = {} local numSkipped = 0 for i = 1, #sets do if not showAdminCategories and sets[i].Name == "Beta" then numSkipped = numSkipped + 1 else setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets) end end return setButtons end local function handleResize() wait() -- neccessary to insure heartbeat happened local itemPreview = setGui.SetPanel.ItemPreview itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X) itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0) itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y) itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y) end local function makeInsertAssetButton() local insertAssetButtonExample = Instance.new("Frame") insertAssetButtonExample.Name = "InsertAssetButtonExample" insertAssetButtonExample.Position = UDim2.new(0,128,0,64) insertAssetButtonExample.Size = UDim2.new(0,64,0,64) insertAssetButtonExample.BackgroundTransparency = 1 insertAssetButtonExample.ZIndex = 6 insertAssetButtonExample.Visible = false local assetId = Instance.new("IntValue") assetId.Name = "AssetId" assetId.Value = 0 assetId.Parent = insertAssetButtonExample local assetName = Instance.new("StringValue") assetName.Name = "AssetName" assetName.Value = "" assetName.Parent = insertAssetButtonExample local button = Instance.new("TextButton") button.Name = "Button" button.Text = "" button.Style = Enum.ButtonStyle.RobloxButton button.Position = UDim2.new(0.025,0,0.025,0) button.Size = UDim2.new(0.95,0,0.95,0) button.ZIndex = 6 button.Parent = insertAssetButtonExample local buttonImage = Instance.new("ImageLabel") buttonImage.Name = "ButtonImage" buttonImage.Image = "" buttonImage.Position = UDim2.new(0,-7,0,-7) buttonImage.Size = UDim2.new(1,14,1,14) buttonImage.BackgroundTransparency = 1 buttonImage.ZIndex = 7 buttonImage.Parent = button local configIcon = buttonImage:clone() configIcon.Name = "ConfigIcon" configIcon.Visible = false configIcon.Position = UDim2.new(1,-23,1,-24) configIcon.Size = UDim2.new(0,16,0,16) configIcon.Image = "" configIcon.ZIndex = 6 configIcon.Parent = insertAssetButtonExample return insertAssetButtonExample end local function showLargePreview(insertButton) if insertButton:FindFirstChild("AssetId") then delay(0,function() game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)) setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value) end) end if insertButton:FindFirstChild("AssetName") then setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value end end local function selectTerrainShape(shape) if currTerrainDropDownFrame then objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape) end end local function createTerrainTypeButton(name, parent) local dropDownTextButton = Instance.new("TextButton") dropDownTextButton.Name = name .. "Button" dropDownTextButton.Font = Enum.Font.ArialBold dropDownTextButton.FontSize = Enum.FontSize.Size14 dropDownTextButton.BorderSizePixel = 0 dropDownTextButton.TextColor3 = Color3.new(1,1,1) dropDownTextButton.Text = name dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.ZIndex = parent.ZIndex + 1 dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16) dropDownTextButton.Position = UDim2.new(0,1,0,0) dropDownTextButton.MouseEnter:connect(function() dropDownTextButton.BackgroundTransparency = 0 dropDownTextButton.TextColor3 = Color3.new(0,0,0) end) dropDownTextButton.MouseLeave:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) end) dropDownTextButton.MouseButton1Click:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then dropDownTextButton.Parent.Visible = false end selectTerrainShape(terrainShapeMap[dropDownTextButton.Text]) end) return dropDownTextButton end local function createTerrainDropDownMenu(zIndex) local dropDown = Instance.new("Frame") dropDown.Name = "TerrainDropDown" dropDown.BackgroundColor3 = Color3.new(0,0,0) dropDown.BorderColor3 = Color3.new(1,0,0) dropDown.Size = UDim2.new(0,200,0,0) dropDown.Visible = false dropDown.ZIndex = zIndex dropDown.Parent = setGui for i = 1, #terrainShapes do local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown) shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset)) shapeButton.Parent = dropDown dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset)) end dropDown.MouseLeave:connect(function() dropDown.Visible = false end) end local function createDropDownMenuButton(parent) local dropDownButton = Instance.new("ImageButton") dropDownButton.Name = "DropDownButton" dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509" dropDownButton.BackgroundTransparency = 1 dropDownButton.Size = UDim2.new(0,16,0,16) dropDownButton.Position = UDim2.new(1,-24,0,6) dropDownButton.ZIndex = parent.ZIndex + 2 dropDownButton.Parent = parent if not setGui:FindFirstChild("TerrainDropDown") then createTerrainDropDownMenu(8) end dropDownButton.MouseButton1Click:connect(function() setGui.TerrainDropDown.Visible = true setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y) currTerrainDropDownFrame = parent end) end local function buildInsertButton() local insertButton = makeInsertAssetButton() insertButton.Name = "InsertAssetButton" insertButton.Visible = true if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then createDropDownMenuButton(insertButton) end local lastEnter = nil local mouseEnterCon = insertButton.MouseEnter:connect(function() lastEnter = insertButton delay(0.1,function() if lastEnter == insertButton then showLargePreview(insertButton) end end) end) return insertButton, mouseEnterCon end local function realignButtonGrid(columns) local x = 0 local y = 0 for i = 1, #insertButtons do insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y) x = x + 1 if x >= columns then x = 0 y = y + 1 end end end local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId) if visible then insertFrame.AssetName.Value = name insertFrame.AssetId.Value = assetId local newImageUrl = SmallThumbnailUrl .. assetId if newImageUrl ~= insertFrame.Button.ButtonImage.Image then delay(0,function() game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId) if insertFrame:findFirstChild("Button") then insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId end end) end table.insert(insertButtonCons, insertFrame.Button.MouseButton1Click:connect(function() -- special case for water, show water selection gui local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability") waterGui.Visible = isWaterSelected if isWaterSelected then objectSelected(name, tonumber(assetId), nil) else objectSelected(name, tonumber(assetId)) end end) ) insertFrame.Visible = true else insertFrame.Visible = false end end local function loadSectionOfItems(setGui, rows, columns) local pageSize = rows * columns if arrayPosition > #contents then return end local origArrayPos = arrayPosition local yCopy = 0 for i = 1, pageSize + 1 do if arrayPosition >= #contents + 1 then break end local buttonCon insertButtons[arrayPosition], buttonCon = buildInsertButton() table.insert(insertButtonCons,buttonCon) insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame arrayPosition = arrayPosition + 1 end realignButtonGrid(columns) local indexCopy = origArrayPos for index = origArrayPos, arrayPosition do if insertButtons[index] then if contents[index] then -- we don't want water to have a drop down button if contents[index].Name == "Water" then if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy() end end local assetId if useAssetVersionId then assetId = contents[index].AssetVersionId else assetId = contents[index].AssetId end setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId) else break end else break end indexCopy = index end end local function setSetIndex() Data.Category[Data.CurrentCategory].Index = 0 rows = 7 columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) contents = Data.Category[Data.CurrentCategory].Contents if contents then -- remove our buttons and their connections for i = 1, #insertButtons do insertButtons[i]:remove() end for i = 1, #insertButtonCons do if insertButtonCons[i] then insertButtonCons[i]:disconnect() end end insertButtonCons = {} insertButtons = {} arrayPosition = 1 loadSectionOfItems(setGui, rows, columns) end end local function selectSet(button, setName, setId, setIndex) if button and Data.Category[Data.CurrentCategory] ~= nil then if button ~= Data.Category[Data.CurrentCategory].Button then Data.Category[Data.CurrentCategory].Button = button if SetCache[setId] == nil then SetCache[setId] = game:GetService("InsertService"):GetCollection(setId) end Data.Category[Data.CurrentCategory].Contents = SetCache[setId] Data.Category[Data.CurrentCategory].SetName = setName Data.Category[Data.CurrentCategory].SetId = setId end setSetIndex() end end local function selectCategoryPage(buttons, page) if buttons ~= Data.CurrentCategory then if Data.CurrentCategory then for key, button in pairs(Data.CurrentCategory) do button.Visible = false end end Data.CurrentCategory = buttons if Data.Category[Data.CurrentCategory] == nil then Data.Category[Data.CurrentCategory] = {} if #buttons > 0 then selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0) end else Data.Category[Data.CurrentCategory].Button = nil selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index) end end end local function selectCategory(category) selectCategoryPage(category, 0) end local function resetAllSetButtonSelection() local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren() for i = 1, #setButtons do if setButtons[i]:IsA("TextButton") then setButtons[i].Selected = false setButtons[i].BackgroundTransparency = 1 setButtons[i].TextColor3 = Color3.new(1,1,1) setButtons[i].BackgroundColor3 = Color3.new(1,1,1) end end end local function populateSetsFrame() local currRow = 0 for i = 1, #userCategoryButtons do local button = userCategoryButtons[i] button.Visible = true button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset) button.Parent = setGui.SetPanel.Sets.SetsLists if i == 1 then -- we will have this selected by default, so show it button.Selected = true button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 end button.MouseEnter:connect(function() if not button.Selected then button.BackgroundTransparency = 0 button.TextColor3 = Color3.new(0,0,0) end end) button.MouseLeave:connect(function() if not button.Selected then button.BackgroundTransparency = 1 button.TextColor3 = Color3.new(1,1,1) end end) button.MouseButton1Click:connect(function() resetAllSetButtonSelection() button.Selected = not button.Selected button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0) end) currRow = currRow + 1 end local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren() -- set first category as loaded for default if buttons then for i = 1, #buttons do if buttons[i]:IsA("TextButton") then selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0) selectCategory(userCategoryButtons) break end end end end setGui = createSetGui() waterGui, waterTypeChangedEvent = createWaterGui() waterGui.Position = UDim2.new(0,55,0,0) waterGui.Parent = setGui setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size if prop == "AbsoluteSize" then handleResize() setSetIndex() end end) local scrollFrame, controlFrame = t.CreateTrueScrollingFrame() scrollFrame.Size = UDim2.new(0.54,0,0.85,0) scrollFrame.Position = UDim2.new(0.24,0,0.085,0) scrollFrame.Name = "ItemsFrame" scrollFrame.ZIndex = 6 scrollFrame.Parent = setGui.SetPanel scrollFrame.BackgroundTransparency = 1 drillDownSetZIndex(controlFrame,7) controlFrame.Parent = setGui.SetPanel controlFrame.Position = UDim2.new(0.76, 5, 0, 0) local debounce = false controlFrame.ScrollBottom.Changed:connect(function(prop) if controlFrame.ScrollBottom.Value == true then if debounce then return end debounce = true loadSectionOfItems(setGui, rows, columns) debounce = false end end) local userData = {} for id = 1, #userIdsForSets do local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id]) if newUserData and #newUserData > 2 then -- start at #3 to skip over My Decals and My Models for each account for category = 3, #newUserData do if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first table.insert(userData,1,newUserData[category]) else table.insert(userData, newUserData[category]) end end end end if userData then userCategoryButtons = processCategory(userData) end rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight) columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) populateSetsFrame() insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function() setGui.SetPanel.Visible = false if dialogClosed then dialogClosed() end end) local setVisibilityFunction = function(visible) if visible then setGui.SetPanel.Visible = true else setGui.SetPanel.Visible = false end end local getVisibilityFunction = function() if setGui then if setGui:FindFirstChild("SetPanel") then return setGui.SetPanel.Visible end end return false end return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent end t.CreateTerrainMaterialSelector = function(size,position) local terrainMaterialSelectionChanged = Instance.new("BindableEvent") terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged" local selectedButton = nil local frame = Instance.new("Frame") frame.Name = "TerrainMaterialSelector" if size then frame.Size = size else frame.Size = UDim2.new(0, 245, 0, 230) end if position then frame.Position = position end frame.BorderSizePixel = 0 frame.BackgroundColor3 = Color3.new(0,0,0) frame.Active = true terrainMaterialSelectionChanged.Parent = frame local waterEnabled = true -- todo: turn this on when water is ready local materialToImageMap = {} local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"} if waterEnabled then table.insert(materialNames,"Water") end local currentMaterial = 1 function getEnumFromName(choice) if choice == "Grass" then return 1 end if choice == "Sand" then return 2 end if choice == "Erase" then return 0 end if choice == "Brick" then return 3 end if choice == "Granite" then return 4 end if choice == "Asphalt" then return 5 end if choice == "Iron" then return 6 end if choice == "Aluminum" then return 7 end if choice == "Gold" then return 8 end if choice == "Plank" then return 9 end if choice == "Log" then return 10 end if choice == "Gravel" then return 11 end if choice == "Cinder Block" then return 12 end if choice == "Stone Wall" then return 13 end if choice == "Concrete" then return 14 end if choice == "Plastic (red)" then return 15 end if choice == "Plastic (blue)" then return 16 end if choice == "Water" then return 17 end end function getNameFromEnum(choice) if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end if waterEnabled then if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end end end local function updateMaterialChoice(choice) currentMaterial = getEnumFromName(choice) terrainMaterialSelectionChanged:Fire(currentMaterial) end -- we so need a better way to do this for i,v in pairs(materialNames) do materialToImageMap[v] = {} if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112" elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652" elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537" elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153" elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038" elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093" elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995" elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118" elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848" elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924" elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015" elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051" elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206" elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103" elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804" elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059" elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474" else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!! end end local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid") scrollFrame.Size = UDim2.new(0.85,0,1,0) scrollFrame.Position = UDim2.new(0,0,0,0) scrollFrame.Parent = frame scrollUp.Parent = frame scrollUp.Visible = true scrollUp.Position = UDim2.new(1,-19,0,0) scrollDown.Parent = frame scrollDown.Visible = true scrollDown.Position = UDim2.new(1,-19,1,-17) local function goToNewMaterial(buttonWrap, materialName) updateMaterialChoice(materialName) buttonWrap.BackgroundTransparency = 0 selectedButton.BackgroundTransparency = 1 selectedButton = buttonWrap end local function createMaterialButton(name) local buttonWrap = Instance.new("TextButton") buttonWrap.Text = "" buttonWrap.Size = UDim2.new(0,32,0,32) buttonWrap.BackgroundColor3 = Color3.new(1,1,1) buttonWrap.BorderSizePixel = 0 buttonWrap.BackgroundTransparency = 1 buttonWrap.AutoButtonColor = false buttonWrap.Name = tostring(name) local imageButton = Instance.new("ImageButton") imageButton.AutoButtonColor = false imageButton.BackgroundTransparency = 1 imageButton.Size = UDim2.new(0,30,0,30) imageButton.Position = UDim2.new(0,1,0,1) imageButton.Name = tostring(name) imageButton.Parent = buttonWrap imageButton.Image = materialToImageMap[name].Regular local enumType = Instance.new("NumberValue") enumType.Name = "EnumType" enumType.Parent = buttonWrap enumType.Value = 0 imageButton.MouseEnter:connect(function() buttonWrap.BackgroundTransparency = 0 end) imageButton.MouseLeave:connect(function() if selectedButton ~= buttonWrap then buttonWrap.BackgroundTransparency = 1 end end) imageButton.MouseButton1Click:connect(function() if selectedButton ~= buttonWrap then goToNewMaterial(buttonWrap, tostring(name)) end end) return buttonWrap end for i = 1, #materialNames do local imageButton = createMaterialButton(materialNames[i]) if materialNames[i] == "Grass" then -- always start with grass as the default selectedButton = imageButton imageButton.BackgroundTransparency = 0 end imageButton.Parent = scrollFrame end local forceTerrainMaterialSelection = function(newMaterialType) if not newMaterialType then return end if currentMaterial == newMaterialType then return end local matName = getNameFromEnum(newMaterialType) local buttons = scrollFrame:GetChildren() for i = 1, #buttons do if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end if string.find(buttons[i].Name, matName) then goToNewMaterial(buttons[i],matName) return end end end frame.Changed:connect(function ( prop ) if prop == "AbsoluteSize" then recalculateScroll() end end) recalculateScroll() return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection end t.CreateLoadingFrame = function(name,size,position) game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053") local loadingFrame = Instance.new("Frame") loadingFrame.Name = "LoadingFrame" loadingFrame.Style = Enum.FrameStyle.RobloxRound if size then loadingFrame.Size = size else loadingFrame.Size = UDim2.new(0,300,0,160) end if position then loadingFrame.Position = position else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end local loadingBar = Instance.new("Frame") loadingBar.Name = "LoadingBar" loadingBar.BackgroundColor3 = Color3.new(0,0,0) loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255) loadingBar.Position = UDim2.new(0,0,0,41) loadingBar.Size = UDim2.new(1,0,0,30) loadingBar.Parent = loadingFrame local loadingGreenBar = Instance.new("ImageLabel") loadingGreenBar.Name = "LoadingGreenBar" loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053" loadingGreenBar.Position = UDim2.new(0,0,0,0) loadingGreenBar.Size = UDim2.new(0,0,1,0) loadingGreenBar.Visible = false loadingGreenBar.Parent = loadingBar local loadingPercent = Instance.new("TextLabel") loadingPercent.Name = "LoadingPercent" loadingPercent.BackgroundTransparency = 1 loadingPercent.Position = UDim2.new(0,0,1,0) loadingPercent.Size = UDim2.new(1,0,0,14) loadingPercent.Font = Enum.Font.Arial loadingPercent.Text = "0%" loadingPercent.FontSize = Enum.FontSize.Size14 loadingPercent.TextColor3 = Color3.new(1,1,1) loadingPercent.Parent = loadingBar local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(0.5,-60,1,-40) cancelButton.Size = UDim2.new(0,120,0,40) cancelButton.Font = Enum.Font.Arial cancelButton.FontSize = Enum.FontSize.Size18 cancelButton.TextColor3 = Color3.new(1,1,1) cancelButton.Text = "Cancel" cancelButton.Style = Enum.ButtonStyle.RobloxButton cancelButton.Parent = loadingFrame local loadingName = Instance.new("TextLabel") loadingName.Name = "loadingName" loadingName.BackgroundTransparency = 1 loadingName.Size = UDim2.new(1,0,0,18) loadingName.Position = UDim2.new(0,0,0,2) loadingName.Font = Enum.Font.Arial loadingName.Text = name loadingName.TextColor3 = Color3.new(1,1,1) loadingName.TextStrokeTransparency = 1 loadingName.FontSize = Enum.FontSize.Size18 loadingName.Parent = loadingFrame local cancelButtonClicked = Instance.new("BindableEvent") cancelButtonClicked.Name = "CancelButtonClicked" cancelButtonClicked.Parent = cancelButton cancelButton.MouseButton1Click:connect(function() cancelButtonClicked:Fire() end) local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength) if percent and type(percent) ~= "number" then error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead") end local newSize = nil if percent < 0 then newSize = UDim2.new(0,0,1,0) elseif percent > 1 then newSize = UDim2.new(1,0,1,0) else newSize = UDim2.new(percent,0,1,0) end if tweenAction then if not tweenLength then error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument") end if (newSize.X.Scale > 0) then loadingGreenBar.Visible = true loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true) else loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true, function() if (newSize.X.Scale < 0) then loadingGreenBar.Visible = false end end) end else loadingGreenBar.Size = newSize loadingGreenBar.Visible = (newSize.X.Scale > 0) end end loadingGreenBar.Changed:connect(function(prop) if prop == "Size" then loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%" end end) return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked end t.CreatePluginFrame = function (name,size,position,scrollable,parent) function createMenuButton(size,position,text,fontsize,name,parent) local button = Instance.new("TextButton",parent) button.AutoButtonColor = false button.Name = name button.BackgroundTransparency = 1 button.Position = position button.Size = size button.Font = Enum.Font.ArialBold button.FontSize = fontsize button.Text = text button.TextColor3 = Color3.new(1,1,1) button.BorderSizePixel = 0 button.BackgroundColor3 = Color3.new(20/255,20/255,20/255) button.MouseEnter:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 1 end) return button end local dragBar = Instance.new("Frame",parent) dragBar.Name = tostring(name) .. "DragBar" dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) dragBar.BorderColor3 = Color3.new(0,0,0) if size then dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0) else dragBar.Size = UDim2.new(0,183,0,20) end if position then dragBar.Position = position end dragBar.Active = true dragBar.Draggable = true --dragBar.Visible = false dragBar.MouseEnter:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255) end) dragBar.MouseLeave:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) end) -- plugin name label local pluginNameLabel = Instance.new("TextLabel",dragBar) pluginNameLabel.Name = "BarNameLabel" pluginNameLabel.Text = " " .. tostring(name) pluginNameLabel.TextColor3 = Color3.new(1,1,1) pluginNameLabel.TextStrokeTransparency = 0 pluginNameLabel.Size = UDim2.new(1,0,1,0) pluginNameLabel.Font = Enum.Font.ArialBold pluginNameLabel.FontSize = Enum.FontSize.Size18 pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left pluginNameLabel.BackgroundTransparency = 1 -- close button local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar) local closeEvent = Instance.new("BindableEvent") closeEvent.Name = "CloseEvent" closeEvent.Parent = closeButton closeButton.MouseButton1Click:connect(function () closeEvent:Fire() closeButton.BackgroundTransparency = 1 end) -- help button local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar) local helpFrame = Instance.new("Frame",dragBar) helpFrame.Name = "HelpFrame" helpFrame.BackgroundColor3 = Color3.new(0,0,0) helpFrame.Size = UDim2.new(0,300,0,552) helpFrame.Position = UDim2.new(1,5,0,0) helpFrame.Active = true helpFrame.BorderSizePixel = 0 helpFrame.Visible = false helpButton.MouseButton1Click:connect(function( ) helpFrame.Visible = not helpFrame.Visible if helpFrame.Visible then helpButton.Selected = true helpButton.BackgroundTransparency = 0 local screenGui = getScreenGuiAncestor(helpFrame) if screenGui then if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0) else -- position on right hand side helpFrame.Position = UDim2.new(1,5,0,0) end else helpFrame.Position = UDim2.new(1,5,0,0) end else helpButton.Selected = false helpButton.BackgroundTransparency = 1 end end) local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar) minimizeButton.TextYAlignment = Enum.TextYAlignment.Top local minimizeFrame = Instance.new("Frame",dragBar) minimizeFrame.Name = "MinimizeFrame" minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255) minimizeFrame.BorderColor3 = Color3.new(0,0,0) minimizeFrame.Position = UDim2.new(0,0,1,0) if size then minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0) else minimizeFrame.Size = UDim2.new(0,183,0,50) end minimizeFrame.Visible = false local minimizeBigButton = Instance.new("TextButton",minimizeFrame) minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20) minimizeBigButton.Name = "MinimizeButton" minimizeBigButton.Size = UDim2.new(0,100,0,40) minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton minimizeBigButton.Font = Enum.Font.ArialBold minimizeBigButton.FontSize = Enum.FontSize.Size18 minimizeBigButton.TextColor3 = Color3.new(1,1,1) minimizeBigButton.Text = "Show" local separatingLine = Instance.new("Frame",dragBar) separatingLine.Name = "SeparatingLine" separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255) separatingLine.BorderSizePixel = 0 separatingLine.Position = UDim2.new(1,-18,0.5,-7) separatingLine.Size = UDim2.new(0,1,0,14) local otherSeparatingLine = separatingLine:clone() otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7) otherSeparatingLine.Parent = dragBar local widgetContainer = Instance.new("Frame",dragBar) widgetContainer.Name = "WidgetContainer" widgetContainer.BackgroundTransparency = 1 widgetContainer.Position = UDim2.new(0,0,1,0) widgetContainer.BorderColor3 = Color3.new(0,0,0) if not scrollable then widgetContainer.BackgroundTransparency = 0 widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255) end if size then if scrollable then widgetContainer.Size = size else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset) end else if scrollable then widgetContainer.Size = UDim2.new(0,163,0,400) else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400) end end if position then widgetContainer.Position = position + UDim2.new(0,0,0,20) end local frame,control,verticalDragger = nil if scrollable then --frame for widgets frame,control = t.CreateTrueScrollingFrame() frame.Size = UDim2.new(1, 0, 1, 0) frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255) frame.BorderColor3 = Color3.new(0,0,0) frame.Active = true frame.Parent = widgetContainer control.Parent = dragBar control.BackgroundColor3 = Color3.new(72/255,72/255,72/255) control.BorderSizePixel = 0 control.BackgroundTransparency = 0 control.Position = UDim2.new(1,-21,1,1) if size then control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset) else control.Size = UDim2.new(0,21,0,400) end control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20) local fakeLine = Instance.new("Frame",control) fakeLine.Name = "FakeLine" fakeLine.BorderSizePixel = 0 fakeLine.BackgroundColor3 = Color3.new(0,0,0) fakeLine.Size = UDim2.new(0,1,1,1) fakeLine.Position = UDim2.new(1,0,0,0) verticalDragger = Instance.new("TextButton",widgetContainer) verticalDragger.ZIndex = 2 verticalDragger.AutoButtonColor = false verticalDragger.Name = "VerticalDragger" verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) verticalDragger.BorderColor3 = Color3.new(0,0,0) verticalDragger.Size = UDim2.new(1,20,0,20) verticalDragger.Position = UDim2.new(0,0,1,0) verticalDragger.Active = true verticalDragger.Text = "" local scrubFrame = Instance.new("Frame",verticalDragger) scrubFrame.Name = "ScrubFrame" scrubFrame.BackgroundColor3 = Color3.new(1,1,1) scrubFrame.BorderSizePixel = 0 scrubFrame.Position = UDim2.new(0.5,-5,0.5,0) scrubFrame.Size = UDim2.new(0,10,0,1) scrubFrame.ZIndex = 5 local scrubTwo = scrubFrame:clone() scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2) scrubTwo.Parent = verticalDragger local scrubThree = scrubFrame:clone() scrubThree.Position = UDim2.new(0.5,-5,0.5,2) scrubThree.Parent = verticalDragger local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent)) areaSoak.Name = "AreaSoak" areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.BackgroundTransparency = 1 areaSoak.BorderSizePixel = 0 areaSoak.Text = "" areaSoak.ZIndex = 10 areaSoak.Visible = false areaSoak.Active = true local draggingVertical = false local startYPos = nil verticalDragger.MouseEnter:connect(function () verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255) end) verticalDragger.MouseLeave:connect(function () verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) end) verticalDragger.MouseButton1Down:connect(function(x,y) draggingVertical = true areaSoak.Visible = true startYPos = y end) areaSoak.MouseButton1Up:connect(function ( ) draggingVertical = false areaSoak.Visible = false end) areaSoak.MouseMoved:connect(function(x,y) if not draggingVertical then return end local yDelta = y - startYPos if not control.ScrollDownButton.Visible and yDelta > 0 then return end if (widgetContainer.Size.Y.Offset + yDelta) < 150 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150) control.Size = UDim2.new (0,21,0,150) return end startYPos = y if widgetContainer.Size.Y.Offset + yDelta >= 0 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta) control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta ) end end) end local function switchMinimize() minimizeFrame.Visible = not minimizeFrame.Visible if scrollable then frame.Visible = not frame.Visible verticalDragger.Visible = not verticalDragger.Visible control.Visible = not control.Visible else widgetContainer.Visible = not widgetContainer.Visible end if minimizeFrame.Visible then minimizeButton.Text = "+" else minimizeButton.Text = "-" end end minimizeBigButton.MouseButton1Click:connect(function ( ) switchMinimize() end) minimizeButton.MouseButton1Click:connect(function( ) switchMinimize() end) if scrollable then return dragBar, frame, helpFrame, closeEvent else return dragBar, widgetContainer, helpFrame, closeEvent end end t.Help = function(funcNameOrFunc) --input argument can be a string or a function. Should return a description (of arguments and expected side effects) if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then return "Function CreatePropertyDropDownMenu. " .. "Arguments: (instance, propertyName, enumType). " .. "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'" end if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then return "Function CreateDropDownMenu. " .. "Arguments: (items, onItemSelected). " .. "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items" end if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then return "Function CreateMessageDialog. " .. "Arguments: (title, message, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button" end if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then return "Function CreateStyledMessageDialog. " .. "Arguments: (title, message, style, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm" end if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then return "Function GetFontHeight. " .. "Arguments: (font, fontSize). " .. "Side effect: returns the size in pixels of the given font + fontSize" end if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then end if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then return "Function CreateScrollingFrame. " .. "Arguments: (orderList, style) " .. "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)" end if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then return "Function CreateTrueScrollingFrame. " .. "Arguments: (nil) " .. "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit." end if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then return "Function AutoTruncateTextObject. " .. "Arguments: (textLabel) " .. "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument" end if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then return "Function CreateSlider. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then return "Function CreateSliderNew. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then return "Function CreateLoadingFrame. " .. "Arguments: (name, size, position) " .. "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog." end if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then return "Function CreateTerrainMaterialSelector. " .. "Arguments: (size, position) " .. "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected." end end -- A couple of necessary functions local function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end end local function waitForProperty(instance, property) while not instance[property] do instance.Changed:wait() end end waitForChild(game,"Players") waitForProperty(game.Players,"LocalPlayer") local player = game.Players.LocalPlayer local RbxGui,msg = t if not RbxGui then print("could not find RbxGui!") return end --- Begin Locals waitForChild(game,"Players") -- don't do anything if we are in an empty game if #game.Players:GetChildren() < 1 then game.Players.ChildAdded:wait() end local tilde = "~" local backquote = "`" game:GetService("GuiService"):AddKey(tilde) -- register our keys game:GetService("GuiService"):AddKey(backquote) local player = game.Players.LocalPlayer local backpack = script.Parent.Backpack local screen = script.Parent local openCloseDebounce = false local backpackItems = {} local buttons = {} local debounce = false local guiTweenSpeed = 1 local browsingMenu = false local mouseEnterCons = {} local mouseClickCons = {} local characterChildAddedCon = nil local characterChildRemovedCon = nil local backpackAddCon = nil local humanoidDiedCon = nil local backpackButtonClickCon = nil local guiServiceKeyPressCon = nil local playerBackpack = player.Backpack local gearPreview = backpack.Gear.GearPreview local scroller = backpack.Gear.GearGridScrollingArea local currentLoadout = backpack.Parent.CurrentLoadout local backpackButton = backpack.Parent.ControlFrame.BackpackButton local gearButton = backpack.Gear.GearGrid.GearButton local grid = backpack.Gear.GearGrid local searchBox = backpack.SearchFrame.SearchBoxFrame.SearchBox local searchButton = backpack.SearchFrame.SearchButton local resetFrame = backpack.SearchFrame local resetButton = backpack.SearchFrame.ResetButton local swapSlot = backpack.SwapSlot -- creating scroll bar early as to make sure items get placed correctly local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid") scrollFrame.Position = UDim2.new(0,0,0,30) scrollFrame.Size = UDim2.new(1,0,1,-30) scrollFrame.Parent = backpack.Gear.GearGrid local scrollBar = Instance.new("Frame") scrollBar.Name = "ScrollBar" scrollBar.BackgroundTransparency = 0.9 scrollBar.BackgroundColor3 = Color3.new(1,1,1) scrollBar.BorderSizePixel = 0 scrollBar.Size = UDim2.new(0, 17, 1, -36) scrollBar.Position = UDim2.new(0,0,0,18) scrollBar.Parent = scroller scrollDown.Position = UDim2.new(0,0,1,-17) scrollUp.Parent = scroller scrollDown.Parent = scroller local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame() scrollFrameLoadout.Position = UDim2.new(0,0,0,0) scrollFrameLoadout.Size = UDim2.new(1,0,1,0) scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList local LoadoutButton = Instance.new("TextButton") LoadoutButton.RobloxLocked = true LoadoutButton.Name = "LoadoutButton" LoadoutButton.Font = Enum.Font.ArialBold LoadoutButton.FontSize = Enum.FontSize.Size14 LoadoutButton.Position = UDim2.new(0,0,0,0) LoadoutButton.Size = UDim2.new(1,0,0,32) LoadoutButton.Style = Enum.ButtonStyle.RobloxButton LoadoutButton.Text = "Loadout #1" LoadoutButton.TextColor3 = Color3.new(1,1,1) LoadoutButton.Parent = scrollFrameLoadout local LoadoutButtonTwo = LoadoutButton:clone() LoadoutButtonTwo.Text = "Loadout #2" LoadoutButtonTwo.Parent = scrollFrameLoadout local LoadoutButtonThree = LoadoutButton:clone() LoadoutButtonThree.Text = "Loadout #3" LoadoutButtonThree.Parent = scrollFrameLoadout local LoadoutButtonFour = LoadoutButton:clone() LoadoutButtonFour.Text = "Loadout #4" LoadoutButtonFour.Parent = scrollFrameLoadout local scrollBarLoadout = Instance.new("Frame") scrollBarLoadout.Name = "ScrollBarLoadout" scrollBarLoadout.BackgroundTransparency = 0.9 scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1) scrollBarLoadout.BorderSizePixel = 0 scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36) scrollBarLoadout.Position = UDim2.new(0,0,0,18) scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea scrollDownLoadout.Position = UDim2.new(0,0,1,-17) scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea -- Begin Functions function removeFromMap(map,object) for i = 1, #map do if map[i] == object then table.remove(map,i) break end end end function robloxLock(instance) instance.RobloxLocked = true children = instance:GetChildren() if children then for i, child in ipairs(children) do robloxLock(child) end end end function resize() local size = 0 if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then size = gearPreview.AbsoluteSize.X * 0.75 else size = gearPreview.AbsoluteSize.Y * 0.75 end gearPreview.GearImage.Size = UDim2.new(0,size,0,size) gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size) resizeGrid() end function addToGrid(child) if not child:IsA("Tool") then if not child:IsA("HopperBin") then return end end if child:FindFirstChild("RobloxBuildTool") then return end for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered if v == child then return end end table.insert(backpackItems,child) local changeCon = child.Changed:connect(function(prop) if prop == "Name" then if buttons[child] then if buttons[child].Image == "" then buttons[child].GearText.Text = child.Name end end end end) local ancestryCon = nil ancestryCon = child.AncestryChanged:connect(function(theChild,theParent) local thisObject = nil for k,v in pairs(backpackItems) do if v == child then thisObject = v break end end waitForProperty(player,"Character") waitForChild(player,"Backpack") if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then if ancestryCon then ancestryCon:disconnect() end if changeCon then changeCon:disconnect() end for k,v in pairs(backpackItems) do if v == thisObject then if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end buttons[v].Parent = nil buttons[v] = nil break end end removeFromMap(backpackItems,thisObject) resizeGrid() else resizeGrid() end updateGridActive() end) resizeGrid() end function buttonClick(button) if button:FindFirstChild("UnequipContextMenu") and not button.Active then button.UnequipContextMenu.Visible = true browsingMenu = true end end function previewGear(button) if not browsingMenu then gearPreview.GearImage.Image = button.Image gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name end end function findEmptySlot() local smallestNum = nil local loadout = currentLoadout:GetChildren() for i = 1, #loadout do if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then local frameNum = tonumber(string.sub(loadout[i].Name,5)) if frameNum == 0 then frameNum = 10 end if not smallestNum or (smallestNum > frameNum) then smallestNum = frameNum end end end if smallestNum == 10 then smallestNum = 0 end return smallestNum end function checkForSwap(button,x,y) local loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) swapGearSlot(slot,button) return true end end end end return false end function resizeGrid() for k,v in pairs(backpackItems) do if not v:FindFirstChild("RobloxBuildTool") then if not buttons[v] then local buttonClone = gearButton:clone() buttonClone.Parent = grid.ScrollingFrame buttonClone.Visible = true buttonClone.Image = v.TextureId if buttonClone.Image == "" then buttonClone.GearText.Text = v.Name end buttonClone.GearReference.Value = v buttonClone.Draggable = true buttons[v] = buttonClone local unequipMenu = getGearContextMenu() unequipMenu.Visible = false unequipMenu.Parent = buttonClone local beginPos = nil buttonClone.DragBegin:connect(function(value) buttonClone.ZIndex = 9 beginPos = value end) buttonClone.DragStopped:connect(function(x,y) if beginPos ~= buttonClone.Position then buttonClone.ZIndex = 1 if not checkForSwap(buttonClone,x,y) then buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true) buttonClone.Draggable = false delay(0.5,function() buttonClone.Draggable = true end) else buttonClone.Position = beginPos end end end) local clickTime = tick() mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end) mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() local newClickTime = tick() if buttonClone.Active and (newClickTime - clickTime) < 0.5 then local slot = findEmptySlot() if slot then buttonClone.ZIndex = 1 swapGearSlot(slot,buttonClone) end else buttonClick(buttonClone) end clickTime = newClickTime end) end end end recalculateScroll() end function showPartialGrid(subset) resetFrame.Visible = true for k,v in pairs(buttons) do v.Parent = nil end for k,v in pairs(subset) do v.Parent = grid.ScrollingFrame end recalculateScroll() end function showEntireGrid() resetFrame.Visible = false for k,v in pairs(buttons) do v.Parent = grid.ScrollingFrame end recalculateScroll() end function inLoadout(gear) local children = currentLoadout:GetChildren() for i = 1, #children do if children[i]:IsA("Frame") then local button = children[i]:GetChildren() if #button > 0 then if button[1].GearReference.Value and button[1].GearReference.Value == gear then return true end end end end return false end function updateGridActive() for k,v in pairs(backpackItems) do if buttons[v] then local gear = nil local gearRef = buttons[v]:FindFirstChild("GearReference") if gearRef then gear = gearRef.Value end if not gear then buttons[v].Active = false elseif inLoadout(gear) then buttons[v].Active = false else buttons[v].Active = true end end end end function centerGear(loadoutChildren) local gearButtons = {} local lastSlotAdd = nil for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then if loadoutChildren[i].Name == "Slot0" then lastSlotAdd = loadoutChildren[i] else table.insert(gearButtons, loadoutChildren[i]) end end end if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end local startPos = ( 1 - (#gearButtons * 0.1) ) / 2 for i = 1, #gearButtons do gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) end end function spreadOutGear(loadoutChildren) for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) if slot == 0 then slot = 10 end loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) end end end function openCloseBackpack(close) if openCloseDebounce then return end openCloseDebounce = true local visible = not backpack.Visible if visible and not close then updateGridActive() local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog, function() backpack.Visible = true loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then loadoutChildren[i].BackgroundTransparency = 0.5 end end spreadOutGear(loadoutChildren) end, function() backpack.Visible = false end) end) backpackButton.Selected = true backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true) delay(guiTweenSpeed/2 + 0.01, function() local children = backpack:GetChildren() for i = 1, #children do if children[i]:IsA("Frame") then children[i].Visible = true end end resizeGrid() resize() openCloseDebounce = false end) else backpackButton.Selected = false local children = backpack:GetChildren() for i = 1, #children do if children[i]:IsA("Frame") then children[i].Visible = false end end loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then loadoutChildren[i].BackgroundTransparency = 1 end end centerGear(loadoutChildren) backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true) delay(guiTweenSpeed/2 + 0.01, function() backpack.Visible = true resizeGrid() resize() pcall(function() game.GuiService:RemoveCenterDialog(backpack) end) openCloseDebounce = false end) end end function loadoutCheck(child, selectState) if not child:IsA("ImageButton") then return end for k,v in pairs(backpackItems) do if buttons[v] then if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then if buttons[v].GearReference.Value == child.GearReference.Value then buttons[v].Active = selectState break end end end end end function clearPreview() gearPreview.GearImage.Image = "" gearPreview.GearStats.GearName.Text = "" end function removeAllEquippedGear(physGear) local stuff = player.Character:GetChildren() for i = 1, #stuff do if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then stuff[i].Parent = playerBackpack end end end function equipGear(physGear) removeAllEquippedGear(physGear) physGear.Parent = player.Character updateGridActive() end function unequipGear(physGear) physGear.Parent = playerBackpack updateGridActive() end function highlight(button) button.TextColor3 = Color3.new(0,0,0) button.BackgroundColor3 = Color3.new(0.8,0.8,0.8) end function clearHighlight(button) button.TextColor3 = Color3.new(1,1,1) button.BackgroundColor3 = Color3.new(0,0,0) end function swapGearSlot(slot,gearButton) if not swapSlot.Value then -- signal loadout to swap a gear out swapSlot.Slot.Value = slot swapSlot.GearButton.Value = gearButton swapSlot.Value = true updateGridActive() end end local UnequipGearMenuClick = function(element, menu) if type(element.Action) ~= "number" then return end local num = element.Action if num == 1 then -- remove from loadout unequipGear(menu.Parent.GearReference.Value) local inventoryButton = menu.Parent local gearToUnequip = inventoryButton.GearReference.Value local loadoutChildren = currentLoadout:GetChildren() local slot = -1 for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then local button = loadoutChildren[i]:GetChildren() if button[1] and button[1].GearReference.Value == gearToUnequip then slot = button[1].SlotNumber.Text break end end end swapGearSlot(slot,nil) end end -- these next two functions are used to stop any use of backpack while the player is dead (can cause issues) function activateBackpack() loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then loadoutChildren[i].BackgroundTransparency = 1 end end backpackButtonClickCon = backpackButton.MouseButton1Click:connect(function() openCloseBackpack() end) guiServiceKeyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) if key == tilde or key == backquote then openCloseBackpack() end end) end function deactivateBackpack() if backpackButtonClickCon then backpackButtonClickCon:disconnect() end if guiServiceKeyPressCon then guiServiceKeyPressCon:disconnect() end openCloseBackpack(true) end function setupCharacterConnections() if backpackAddCon then backpackAddCon:disconnect() end backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) -- make sure we get all the children local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren() for i = 1, #backpackChildren do addToGrid(backpackChildren[i]) end if characterChildAddedCon then characterChildAddedCon:disconnect() end characterChildAddedCon = game.Players.LocalPlayer.Character.ChildAdded:connect(function(child) addToGrid(child) updateGridActive() end) if characterChildRemovedCon then characterChildRemovedCon:disconnect() end characterChildRemovedCon = game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child) updateGridActive() end) if humanoidDiedCon then humanoidDiedCon:disconnect() end local localPlayer = game.Players.LocalPlayer waitForProperty(localPlayer,"Character") waitForChild(localPlayer.Character,"Humanoid") humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(function() deactivateBackpack() end) activateBackpack() wait() centerGear(currentLoadout:GetChildren()) end function removeCharacterConnections() if characterChildAddedCon then characterChildAddedCon:disconnect() end if characterChildRemovedCon then characterChildRemovedCon:disconnect() end if backpackAddCon then backpackAddCon:disconnect() end end function trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end function splitByWhiteSpace(text) if type(text) ~= "string" then return nil end local terms = {} for token in string.gmatch(text, "[^%s]+") do if string.len(token) > 2 then table.insert(terms,token) end end return terms end function filterGear(searchTerm) string.lower(searchTerm) searchTerm = trim(searchTerm) if string.len(searchTerm) < 2 then return nil end local terms = splitByWhiteSpace(searchTerm) local filteredGear = {} for k,v in pairs(backpackItems) do if buttons[v] then local gearString = string.lower(buttons[v].GearReference.Value.Name) gearString = trim(gearString) for i = 1, #terms do if string.match(gearString,terms[i]) then table.insert(filteredGear,buttons[v]) break end end end end return filteredGear end function showSearchGear() local searchText = searchBox.Text searchBox.Text = "Search..." local filteredButtons = filterGear(searchText) if filteredButtons and #filteredButtons > 0 then showPartialGrid(filteredButtons) else showEntireGrid() end end function nukeBackpack() while #buttons > 0 do table.remove(buttons) end buttons = {} while #backpackItems > 0 do table.remove(backpackItems) end backpackItems = {} local scrollingFrameChildren = grid.ScrollingFrame:GetChildren() for i = 1, #scrollingFrameChildren do scrollingFrameChildren[i]:remove() end end function getGearContextMenu() local gearContextMenu = Instance.new("Frame") gearContextMenu.Active = true gearContextMenu.Name = "UnequipContextMenu" gearContextMenu.Size = UDim2.new(0,115,0,70) gearContextMenu.Position = UDim2.new(0,-16,0,-16) gearContextMenu.BackgroundTransparency = 1 gearContextMenu.Visible = false local gearContextMenuButton = Instance.new("TextButton") gearContextMenuButton.Name = "UnequipContextMenuButton" gearContextMenuButton.Text = "" gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault gearContextMenuButton.ZIndex = 4 gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20) gearContextMenuButton.Visible = true gearContextMenuButton.Parent = gearContextMenu local elementHeight = 12 local contextMenuElements = {} local contextMenuElementsName = {"Remove Hotkey"} for i = 1, #contextMenuElementsName do local element = {} element.Type = "Button" element.Text = contextMenuElementsName[i] element.Action = i element.DoIt = UnequipGearMenuClick table.insert(contextMenuElements,element) end for i, contextElement in ipairs(contextMenuElements) do local element = contextElement if element.Type == "Button" then local button = Instance.new("TextButton") button.Name = "UnequipContextButton" .. i button.BackgroundColor3 = Color3.new(0,0,0) button.BorderSizePixel = 0 button.TextXAlignment = Enum.TextXAlignment.Left button.Text = " " .. contextElement.Text button.Font = Enum.Font.Arial button.FontSize = Enum.FontSize.Size14 button.Size = UDim2.new(1, 8, 0, elementHeight) button.Position = UDim2.new(0,0,0,elementHeight * i) button.TextColor3 = Color3.new(1,1,1) button.ZIndex = 4 button.Parent = gearContextMenuButton button.MouseButton1Click:connect(function() if button.Active and not gearContextMenu.Parent.Active then local success, result = pcall(function() element.DoIt(element, gearContextMenu) end) browsingMenu = false gearContextMenu.Visible = false clearHighlight(button) clearPreview() end end) button.MouseEnter:connect(function() if button.Active and gearContextMenu.Parent.Active then highlight(button) end end) button.MouseLeave:connect(function() if button.Active and gearContextMenu.Parent.Active then clearHighlight(button) end end) contextElement.Button = button contextElement.Element = button elseif element.Type == "Label" then local frame = Instance.new("Frame") frame.Name = "ContextLabel" .. i frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1, 8, 0, elementHeight) local label = Instance.new("TextLabel") label.Name = "Text1" label.BackgroundTransparency = 1 label.BackgroundColor3 = Color3.new(1,1,1) label.BorderSizePixel = 0 label.TextXAlignment = Enum.TextXAlignment.Left label.Font = Enum.Font.ArialBold label.FontSize = Enum.FontSize.Size14 label.Position = UDim2.new(0.0, 0, 0, 0) label.Size = UDim2.new(0.5, 0, 1, 0) label.TextColor3 = Color3.new(1,1,1) label.ZIndex = 4 label.Parent = frame element.Label1 = label if element.GetText2 then label = Instance.new("TextLabel") label.Name = "Text2" label.BackgroundTransparency = 1 label.BackgroundColor3 = Color3.new(1,1,1) label.BorderSizePixel = 0 label.TextXAlignment = Enum.TextXAlignment.Right label.Font = Enum.Font.Arial label.FontSize = Enum.FontSize.Size14 label.Position = UDim2.new(0.5, 0, 0, 0) label.Size = UDim2.new(0.5, 0, 1, 0) label.TextColor3 = Color3.new(1,1,1) label.ZIndex = 4 label.Parent = frame element.Label2 = label end frame.Parent = gearContextMenuButton element.Label = frame element.Element = frame end end gearContextMenu.ZIndex = 4 gearContextMenu.MouseLeave:connect(function() browsingMenu = false gearContextMenu.Visible = false clearPreview() end) robloxLock(gearContextMenu) return gearContextMenu end local backpackChildren = player.Backpack:GetChildren() for i = 1, #backpackChildren do addToGrid(backpackChildren[i]) end ------------------------- Start Lifelong Connections ----------------------- screen.Changed:connect(function(prop) if prop == "AbsoluteSize" then if debounce then return end debounce = true wait() resize() resizeGrid() debounce = false end end) currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end) currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end) currentLoadout.DescendantAdded:connect(function(descendant) if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then centerGear(currentLoadout:GetChildren()) end end) currentLoadout.DescendantRemoving:connect(function(descendant) if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then wait() centerGear(currentLoadout:GetChildren()) end end) grid.MouseEnter:connect(function() clearPreview() end) grid.MouseLeave:connect(function() clearPreview() end) player.CharacterRemoving:connect(function() removeCharacterConnections() nukeBackpack() end) player.CharacterAdded:connect(function() setupCharacterConnections() end) player.ChildAdded:connect(function(child) if child:IsA("Backpack") then playerBackpack = child if backpackAddCon then backpackAddCon:disconnect() end backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) end end) swapSlot.Changed:connect(function() if not swapSlot.Value then updateGridActive() end end) searchBox.FocusLost:connect(function(enterPressed) if enterPressed then showSearchGear() end end) local loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then loadoutChildren[i].ChildRemoved:connect(function() updateGridActive() end) loadoutChildren[i].ChildAdded:connect(function() updateGridActive() end) end end searchButton.MouseButton1Click:connect(function() showSearchGear() end) resetButton.MouseButton1Click:connect(function() showEntireGrid() end) ------------------------- End Lifelong Connections ----------------------- resize() resizeGrid() -- make sure any items in the loadout are accounted for in inventory local loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do loadoutCheck(loadoutChildren[i], false) end if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end -- make sure that inventory is listening to gear reparenting if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then setupCharacterConnections() end if not backpackAddCon then backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) end -- flip it on if we are good backpackButton.Visible = true recalculateScrollLoadout() false BackpackScript -- fixed by iagoMAO#6808, any bugs report to me. -- -- A couple of necessary functions local function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end end local function waitForProperty(instance, property) while not instance[property] do instance.Changed:wait() end end --- Begin Locals waitForChild(game,"Players") waitForProperty(game.Players,"LocalPlayer") local player = game.Players.LocalPlayer --[[waitForChild(game, "LocalBackpack") game.LocalBackpack:SetOldSchoolBackpack(false)--]] waitForChild(script.Parent, "CurrentLoadout") local currentLoadout = script.Parent.CurrentLoadout local maxNumLoadoutItems = 10 waitForChild(currentLoadout.Parent,"Backpack") local guiBackpack = currentLoadout.Parent.Backpack local characterChildAddedCon = nil local keyPressCon = nil local backpackChildCon = nil local debounce = script.Parent.CurrentLoadout.Debounce local waitingOnEnlarge = nil local enlargeFactor = 1.18 local buttonSizeEnlarge = UDim2.new(1 * enlargeFactor,0,1 * enlargeFactor,0) local buttonSizeNormal = UDim2.new(1,0,1,0) local enlargeOverride = true local guiTweenSpeed = 0.5 for i = 0, 9 do game:GetService("GuiService"):AddKey(tostring(i)) -- register our keys end local gearSlots = {} for i = 1, maxNumLoadoutItems do gearSlots[i] = "empty" end local inventory = {} local lastLoadout = {} --- End Locals -- Begin Functions local function kill(prop,con,gear) if con then con:disconnect() end if prop == true and gear then reorganizeLoadout(gear,false) end end function removeGear(gear) local emptySlot = nil for i = 1, #gearSlots do if gearSlots[i] == gear and gear.Parent ~= nil then emptySlot = i break end end if emptySlot then if gearSlots[emptySlot].GearReference.Value then if gearSlots[emptySlot].GearReference.Value.Parent == game.Players.LocalPlayer.Character then -- if we currently have this equipped, unequip it gearSlots[emptySlot].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack end if gearSlots[emptySlot].GearReference.Value:IsA("HopperBin") and gearSlots[emptySlot].GearReference.Value.Active then -- this is an active hopperbin gearSlots[emptySlot].GearReference.Value:Disable() gearSlots[emptySlot].GearReference.Value.Active = false end end gearSlots[emptySlot] = "empty" local centerizeX = gear.Size.X.Scale/2 local centerizeY = gear.Size.Y.Scale/2 gear:TweenSizeAndPosition(UDim2.new(0,0,0,0), UDim2.new(gear.Position.X.Scale + centerizeX,gear.Position.X.Offset,gear.Position.Y.Scale + centerizeY,gear.Position.Y.Offset), Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/4,true) delay(guiTweenSpeed/2, function() gear:remove() end) end end function insertGear(gear, addToSlot) local pos = nil if not addToSlot then for i = 1, #gearSlots do if gearSlots[i] == "empty" then pos = i break end end if pos == 1 and gearSlots[1] ~= "empty" then gear:remove() return end -- we are currently full, can't add in else pos = addToSlot -- push all gear down one slot local start = 1 for i = 1, #gearSlots do if gearSlots[i] == "empty" then start = i break end end for i = start, pos + 1, -1 do gearSlots[i] = gearSlots[i - 1] if i == 10 then gearSlots[i].SlotNumber.Text = "0" gearSlots[i].SlotNumberDownShadow.Text = "0" gearSlots[i].SlotNumberUpShadow.Text = "0" else gearSlots[i].SlotNumber.Text = i gearSlots[i].SlotNumberDownShadow.Text = i gearSlots[i].SlotNumberUpShadow.Text = i end end end gearSlots[pos] = gear if pos ~= maxNumLoadoutItems then if(type(tostring(pos)) == "string") then local posString = tostring(pos) gear.SlotNumber.Text = posString gear.SlotNumberDownShadow.Text = posString gear.SlotNumberUpShadow.Text = posString end else -- tenth gear doesn't follow mathematical pattern :( gear.SlotNumber.Text = "0" gear.SlotNumberDownShadow.Text = "0" gear.SlotNumberUpShadow.Text = "0" end gear.Visible = true local con = nil con = gear.Kill.Changed:connect(function(prop) kill(prop,con,gear) end) end function reorganizeLoadout(gear, inserting, equipped, addToSlot) if inserting then -- add in gear insertGear(gear, addToSlot) else removeGear(gear) end if gear ~= "empty" then gear.ZIndex = 1 end end function checkToolAncestry(child,parent) if child:FindFirstChild("RobloxBuildTool") then return end -- don't show roblox build tools if child:IsA("Tool") or child:IsA("HopperBin") then for i = 1, #gearSlots do if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then if parent == nil then gearSlots[i].Kill.Value = true return false elseif child.Parent == player.Character then gearSlots[i].Selected = true return true elseif child.Parent == player.Backpack then if child:IsA("Tool") then gearSlots[i].Selected = false end return true else gearSlots[i].Kill.Value = true return false end return true end end end end function removeAllEquippedGear(physGear) local stuff = player.Character:GetChildren() for i = 1, #stuff do if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then if stuff[i]:IsA("Tool") then stuff[i].Parent = player.Backpack end if stuff[i]:IsA("HopperBin") then stuff[i]:Disable() end end end end function hopperBinSwitcher(numKey, physGear) if not physGear then return end physGear:ToggleSelect() if gearSlots[numKey] == "empty" then return end if not physGear.Active then gearSlots[numKey].Selected = false normalizeButton(gearSlots[numKey]) else gearSlots[numKey].Selected = true enlargeButton(gearSlots[numKey]) end end function toolSwitcher(numKey) if not gearSlots[numKey] then return end local physGear = gearSlots[numKey].GearReference.Value if physGear == nil then return end removeAllEquippedGear(physGear) -- we don't remove this gear, as then we get a double switcheroo local key = numKey if numKey == 0 then key = 10 end for i = 1, #gearSlots do if gearSlots[i] and gearSlots[i] ~= "empty" and i ~= key then normalizeButton(gearSlots[i]) gearSlots[i].Selected = false if gearSlots[i].GearReference and gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value:IsA("HopperBin") and gearSlots[i].GearReference.Value.Active then gearSlots[i].GearReference.Value:ToggleSelect() end end end if physGear:IsA("HopperBin") then hopperBinSwitcher(numKey,physGear) else if physGear.Parent == player.Character then physGear.Parent = player.Backpack gearSlots[numKey].Selected = false normalizeButton(gearSlots[numKey]) else physGear.Parent = player.Character gearSlots[numKey].Selected = true enlargeButton(gearSlots[numKey]) end end end function activateGear(num) local numKey = nil if num == "0" then numKey = 10 -- why do lua indexes have to start at 1? :( else numKey = tonumber(num) end if(numKey == nil) then return end if gearSlots[numKey] ~= "empty" then toolSwitcher(numKey) end end enlargeButton = function(button) if button.Size.Y.Scale > 1 then return end if not button.Parent then return end if not button.Selected then return end for i = 1, #gearSlots do if gearSlots[i] == "empty" then break end if gearSlots[i] ~= button then normalizeButton(gearSlots[i]) end end if not enlargeOverride then waitingOnEnlarge = button return end if button:IsA("ImageButton") or button:IsA("TextButton") then button.ZIndex = 2 local centerizeX = -(buttonSizeEnlarge.X.Scale - button.Size.X.Scale)/2 local centerizeY = -(buttonSizeEnlarge.Y.Scale - button.Size.Y.Scale)/2 button:TweenSizeAndPosition(buttonSizeEnlarge, UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset), Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/5,enlargeOverride) end end normalizeAllButtons = function() for i = 1, #gearSlots do if gearSlots[i] == "empty" then break end if gearSlots[i] ~= button then normalizeButton(gearSlots[i],0.1) end end end normalizeButton = function(button, speed) if not button then return end if button.Size.Y.Scale <= 1 then return end if button.Selected then return end if not button.Parent then return end local moveSpeed = speed if moveSpeed == nil or type(moveSpeed) ~= "number" then moveSpeed = guiTweenSpeed/5 end if button:IsA("ImageButton") or button:IsA("TextButton") then button.ZIndex = 1 local inverseEnlarge = 1/enlargeFactor local centerizeX = -(buttonSizeNormal.X.Scale - button.Size.X.Scale)/2 local centerizeY = -(buttonSizeNormal.Y.Scale - button.Size.Y.Scale)/2 button:TweenSizeAndPosition(buttonSizeNormal, UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset), Enum.EasingDirection.Out, Enum.EasingStyle.Quad,moveSpeed,enlargeOverride) end end waitForDebounce = function() if debounce.Value then debounce.Changed:wait() end end function pointInRectangle(point,rectTopLeft,rectSize) if point.x > rectTopLeft.x and point.x < (rectTopLeft.x + rectSize.x) then if point.y > rectTopLeft.y and point.y < (rectTopLeft.y + rectSize.y) then return true end end return false end function swapGear(gearClone,toFrame) local toFrameChildren = toFrame:GetChildren() if #toFrameChildren == 1 then if toFrameChildren[1]:FindFirstChild("SlotNumber") then local toSlot = tonumber(toFrameChildren[1].SlotNumber.Text) local gearCloneSlot = tonumber(gearClone.SlotNumber.Text) if toSlot == 0 then toSlot = 10 end if gearCloneSlot == 0 then gearCloneSlot = 10 end gearSlots[toSlot] = gearClone gearSlots[gearCloneSlot] = toFrameChildren[1] toFrameChildren[1].SlotNumber.Text = gearClone.SlotNumber.Text toFrameChildren[1].SlotNumberDownShadow.Text = gearClone.SlotNumber.Text toFrameChildren[1].SlotNumberUpShadow.Text = gearClone.SlotNumber.Text local subString = string.sub(toFrame.Name,5) gearClone.SlotNumber.Text = subString gearClone.SlotNumberDownShadow.Text = subString gearClone.SlotNumberUpShadow.Text = subString gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0) toFrameChildren[1].Position = UDim2.new(toFrameChildren[1].Position.X.Scale,0,toFrameChildren[1].Position.Y.Scale,0) toFrameChildren[1].Parent = gearClone.Parent gearClone.Parent = toFrame end else local slotNum = tonumber(gearClone.SlotNumber.Text) if slotNum == 0 then slotNum = 10 end gearSlots[slotNum] = "empty" -- reset this gear slot local subString = string.sub(toFrame.Name,5) gearClone.SlotNumber.Text = subString gearClone.SlotNumberDownShadow.Text = subString gearClone.SlotNumberUpShadow.Text = subString local toSlotNum = tonumber(gearClone.SlotNumber.Text) if toSlotNum == 0 then toSlotNum = 10 end gearSlots[toSlotNum] = gearClone gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0) gearClone.Parent = toFrame end end function resolveDrag(gearClone,x,y) local mousePoint = Vector2.new(x,y) local frame = gearClone.Parent local frames = frame.Parent:GetChildren() for i = 1, #frames do if frames[i]:IsA("Frame") then if pointInRectangle(mousePoint, frames[i].AbsolutePosition,frames[i].AbsoluteSize) then swapGear(gearClone,frames[i]) saveGearPositions() return true end end end if x < frame.AbsolutePosition.x or x > ( frame.AbsolutePosition.x + frame.AbsoluteSize.x ) then reorganizeLoadout(gearClone,false) saveGearPositions() return false elseif y < frame.AbsolutePosition.y or y > ( frame.AbsolutePosition.y + frame.AbsoluteSize.y ) then reorganizeLoadout(gearClone,false) saveGearPositions() return false else if dragBeginPos then gearClone.Position = dragBeginPos end return -1 end end function saveGearPositions() lastLoadout = {} for i = 1, #gearSlots do if gearSlots[i] and gearSlots[i] ~= "empty" then lastLoadout[i] = gearSlots[i] end end end function unequipAllItems(dontEquipThis) for i = 1, #gearSlots do if gearSlots[i] == "empty" then break end if gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value ~= dontEquipThis then if gearSlots[i].GearReference.Value:IsA("HopperBin") then gearSlots[i].GearReference.Value:Disable() elseif gearSlots[i].GearReference.Value:IsA("Tool") then gearSlots[i].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack end gearSlots[i].Selected = false end end end function showToolTip(button, tip) if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then button.ToolTipLabel.Text = tostring(tip) local xSize = button.ToolTipLabel.TextBounds.X + 6 button.ToolTipLabel.Size = UDim2.new(0,xSize,0,20) button.ToolTipLabel.Position = UDim2.new(0.5,-xSize/2,0,-30) button.ToolTipLabel.Visible = true end end function hideToolTip(button, tip) if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then button.ToolTipLabel.Visible = false end end local addingPlayerChild = function(child, equipped, addToSlot, inventoryGearButton) waitForDebounce() debounce.Value = true if child:FindFirstChild("RobloxBuildTool") then debounce.Value = false return end -- don't show roblox build tools if not child:IsA("Tool") then if not child:IsA("HopperBin") then debounce.Value = false return -- we don't care about anything besides tools (sigh...) end end if not addToSlot then for i = 1, #gearSlots do if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then -- we already have gear, do nothing debounce.Value = false return end end end local gearClone = currentLoadout.TempSlot:clone() gearClone.Name = child.Name gearClone.GearImage.Image = child.TextureId if gearClone.GearImage.Image == "" then gearClone.GearText.Text = child.Name end gearClone.GearReference.Value = child gearClone.MouseEnter:connect(function() if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then showToolTip(gearClone, gearClone.GearReference.Value.ToolTip) end end) gearClone.MouseLeave:connect(function() if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then hideToolTip(gearClone, gearClone.GearReference.Value.ToolTip) end end) local slotToMod = -1 if not addToSlot then for i = 1, #gearSlots do if gearSlots[i] == "empty" then slotToMod = i break end end else slotToMod = addToSlot end if slotToMod == - 1 then debounce.Value = false return end -- No available slot to add in! local slotNum = slotToMod % 10 local parent = currentLoadout:FindFirstChild("Slot"..tostring(slotNum)) gearClone.Parent = parent if inventoryGearButton then local absolutePositionFinal = inventoryGearButton.AbsolutePosition local currentAbsolutePosition = gearClone.AbsolutePosition local diff = absolutePositionFinal - currentAbsolutePosition gearClone.Position = UDim2.new(gearClone.Position.X.Scale,diff.x,gearClone.Position.Y.Scale,diff.y) gearClone.ZIndex = 4 end if addToSlot then reorganizeLoadout(gearClone, true, equipped, addToSlot) else reorganizeLoadout(gearClone, true) end if gearClone.Parent == nil then debounce.Value = false return end -- couldn't fit in (hopper is full!) if equipped then gearClone.Selected = true unequipAllItems(child) delay(guiTweenSpeed + 0.01,function() -- if our gear is equipped, we will want to enlarge it when done moving if gearClone:FindFirstChild("GearReference") and ( (gearClone.GearReference.Value:IsA("Tool") and gearClone.GearReference.Value.Parent == player.Character) or (gearClone.GearReference.Value:IsA("HopperBin") and gearClone.GearReference.Value.Active == true) ) then enlargeButton(gearClone) end end) end local dragBeginPos = nil local clickCon, buttonDeleteCon, mouseEnterCon, mouseLeaveCon, dragStop, dragBegin = nil clickCon = gearClone.MouseButton1Click:connect(function() if not gearClone.Draggable then activateGear(gearClone.SlotNumber.Text) end end) mouseEnterCon = gearClone.MouseEnter:connect(function() if guiBackpack.Visible then gearClone.Draggable = true end end) dragBegin = gearClone.DragBegin:connect(function(pos) dragBeginPos = pos gearClone.ZIndex = 7 local children = gearClone:GetChildren() for i = 1, #children do if children[i]:IsA("TextLabel") then if string.find(children[i].Name,"Shadow") then children[i].ZIndex = 8 else children[i].ZIndex = 9 end elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then children[i].ZIndex = 7 end end end) dragStop = gearClone.DragStopped:connect(function(x,y) if gearClone.Selected then gearClone.ZIndex = 2 else gearClone.ZIndex = 1 end local children = gearClone:GetChildren() for i = 1, #children do if children[i]:IsA("TextLabel") then if string.find(children[i].Name,"Shadow") then children[i].ZIndex = 3 else children[i].ZIndex = 4 end elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then children[i].ZIndex = 2 end end resolveDrag(gearClone,x,y) end) mouseLeaveCon = gearClone.MouseLeave:connect(function() gearClone.Draggable = false end) buttonDeleteCon = gearClone.AncestryChanged:connect(function() if gearClone.Parent and gearClone.Parent.Parent == currentLoadout then return end if clickCon then clickCon:disconnect() end if buttonDeleteCon then buttonDeleteCon:disconnect() end if mouseEnterCon then mouseEnterCon:disconnect() end if mouseLeaveCon then mouseLeaveCon:disconnect() end if dragStop then dragStop:disconnect() end if dragBegin then dragBegin:disconnect() end end) -- this probably isn't necessary since objects are being deleted (probably), but this might still leak just in case local childCon = nil local childChangeCon = nil childCon = child.AncestryChanged:connect(function(newChild,parent) if not checkToolAncestry(newChild,parent) then if childCon then childCon:disconnect() end if childChangeCon then childChangeCon:disconnect() end removeFromInventory(child) elseif parent == game.Players.LocalPlayer.Backpack then normalizeButton(gearClone) end end) childChangeCon = child.Changed:connect(function(prop) if prop == "Name" then if gearClone and gearClone.GearImage.Image == "" then gearClone.GearText.Text = child.Name end end end) debounce.Value = false end function addToInventory(child) if not child:IsA("Tool") or not child:IsA("HopperBin") then return end local slot = nil for i = 1, #inventory do if inventory[i] and inventory[i] == child then return end if not inventory[i] then slot = i end end if slot then inventory[slot] = child elseif #inventory < 1 then inventory[1] = child else inventory[#inventory + 1] = child end end function removeFromInventory(child) for i = 1, #inventory do if inventory[i] == child then table.remove(inventory,i) inventory[i] = nil end end end -- these next two functions are used for safe guarding -- when we are waiting for character to come back after dying function activateLoadout() keyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) activateGear(key) end) currentLoadout.Visible = true end function deactivateLoadout() if keyPressCon then keyPressCon:disconnect() end currentLoadout.Visible = false end function setupBackpackListener() if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end backpackChildCon = player.Backpack.ChildAdded:connect(function(child) addingPlayerChild(child) addToInventory(child) -- now store info in case of death saveGearPositions() end) end function playerCharacterChildAdded(child) addingPlayerChild(child,true) addToInventory(child) -- now store info in case of death saveGearPositions() end -- End Functions -- Begin Script wait() -- let stuff initialize incase this is first heartbeat... waitForChild(player,"Backpack") local backpackChildren = player.Backpack:GetChildren() local size = math.min(10,#backpackChildren) for i = 1, size do addingPlayerChild(backpackChildren[i],false) -- now store info in case of death saveGearPositions() end setupBackpackListener() waitForProperty(player,"Character") for i,v in ipairs(player.Character:GetChildren()) do playerCharacterChildAdded(v) end characterChildAddedCon = player.Character.ChildAdded:connect(function(child) playerCharacterChildAdded(child) end) waitForChild(player.Character,"Humanoid") humanoidDiedCon = player.Character.Humanoid.Died:connect(function() if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end deactivateLoadout() if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end end) player.CharacterRemoving:connect(function() for i = 1, #gearSlots do if gearSlots[i] ~= "empty" then gearSlots[i].Parent = nil gearSlots[i] = "empty" end end end) player.CharacterAdded:connect(function() player = game.Players.LocalPlayer -- make sure we are still looking at the correct character waitForChild(player,"Backpack") local backpackChildren = player.Backpack:GetChildren() -- Make sure we put gear back in where we last had them for i = 1, #backpackChildren do for pos,v in pairs(lastLoadout) do if v["Name"] and v.Name == backpackChildren[i].Name then addingPlayerChild(backpackChildren[i],false,pos) lastLoadout[pos] = nil break end end end setupBackpackListener() if characterChildAddedCon then characterChildAddedCon:disconnect() characterChildAddedCon = nil end characterChildAddedCon = player.Character.ChildAdded:connect(function(child) addingPlayerChild(child,true) -- now store info in case of death saveGearPositions() end) waitForChild(player.Character,"Humanoid") humanoidDiedCon = player.Character.Humanoid.Died:connect(function() deactivateLoadout() if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end end) activateLoadout() end) waitForChild(guiBackpack,"SwapSlot") guiBackpack.SwapSlot.Changed:connect(function() if guiBackpack.SwapSlot.Value then local swapSlot = guiBackpack.SwapSlot local pos = swapSlot.Slot.Value if pos == 0 then pos = 10 end if gearSlots[pos] then reorganizeLoadout(gearSlots[pos],false) end if swapSlot.GearButton.Value then addingPlayerChild(swapSlot.GearButton.Value.GearReference.Value,false,pos) -- now store info in case of death saveGearPositions() end guiBackpack.SwapSlot.Value = false end end) keyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) activateGear(key) end) Dialogs false 4288914085 1 4279970357 1 false false ControlFrame 0 0 0 0 1 0 1 0 0 0 true 1 false 4288914085 1 4279970357 1 false false BottomLeftControl 0 0 1 -46 0 130 0 46 0 0 true 1 false 4288914085 1 4279970357 1 false false NotificationBox 1 -200 0.5 0 0 200 0.419999987 0 0 true 1 false Init --rbxsig%XeVmMtUuu+dXh8pEbcaTkr2m9RJZXY42LaACJ12YYcuPtOUxy4Azi8uMDGU8ZTh7cvZC9BlOWgqmZHKjESSdfOZl0/cgd2JKHPZ2UqiqA1slJa7R5GtCcGXlNPHW8KDYgJGRuwe8h5CSiMDOl6QLTSEegTOG7fzHk/n1AFcRN8I=% --rbxassetid%39250920% --fixed by Carrot#0559 function waitForProperty(instance, name) while not instance[name] do instance.Changed:wait() end end local beter = game.Lighting function waitForDialogChildrenMyLord(beter, name) while not beter:FindFirstChild(name) do beter.ChildAdded:wait() end end local bois = game.Players.LocalPlayer.PlayerGui function waitForFaker(bois, name) while not bois:FindFirstChild(name) do bois.ChildAdded:wait() end end local mainFrame local choices = {} local lastChoice local choiceMap = {} local currentConversationDialog local currentConversationPartner local currentAbortDialogScript local tooFarAwayMessage = "You are too far away to chat!" local tooFarAwaySize = 300 local characterWanderedOffMessage = "Chat ended because you walked away" local characterWanderedOffSize = 350 local conversationTimedOut = "Chat ended because you didn't reply" local conversationTimedOutSize = 350 local player local screenGui local chatNotificationGui local messageDialog local timeoutScript = game.Lighting.ReenableDialogScript local reenableDialogScript = game.Lighting.TimeoutScript local dialogMap = {} local dialogConnections = {} local gui = nil --waitForDialogChildrenMyLord(game,"CoreGui") --waitForDialogChildrenMyLord(game.CoreGui,"RobloxGui") --if game.CoreGui.RobloxGui:FindFirstChild("ControlFrame") then -- gui = game.CoreGui.RobloxGui.ControlFrame --else -- gui = game.CoreGui.RobloxGui --end function currentTone() if currentConversationDialog then return currentConversationDialog.Tone else return Enum.DialogTone.Neutral end end function createChatNotificationGui() chatNotificationGui = Instance.new("BillboardGui") chatNotificationGui.Name = "ChatNotificationGui" chatNotificationGui.ExtentsOffset = Vector3.new(0,1,0) chatNotificationGui.Size = UDim2.new(4, 0, 5.42857122, 0) chatNotificationGui.SizeOffset = Vector2.new(0,0) chatNotificationGui.StudsOffset = Vector3.new(0.4, 4.3, 0) chatNotificationGui.Enabled = true chatNotificationGui.Active = true local image = Instance.new("ImageLabel") image.Name = "Image" image.Active = false image.BackgroundTransparency = 1 image.Position = UDim2.new(0,0,0,0) image.Size = UDim2.new(1.0,0,1.0,0) image.Image = "" image.Parent = chatNotificationGui local button = Instance.new("ImageButton") button.Name = "Button" button.AutoButtonColor = false button.Position = UDim2.new(0.0879999995, 0, 0.0529999994, 0) button.Size = UDim2.new(0.829999983, 0, 0.460000008, 0) button.Image = "" button.BackgroundTransparency = 1 button.Parent = image end function getChatColor(tone) if tone == Enum.DialogTone.Neutral then return Enum.ChatColor.Blue elseif tone == Enum.DialogTone.Friendly then return Enum.ChatColor.Green elseif tone == Enum.DialogTone.Enemy then return Enum.ChatColor.Red end end function styleChoices(tone) for i, obj in pairs(choices) do resetColor(obj, tone) end resetColor(lastChoice, tone) end function styleMainFrame(tone) if tone == Enum.DialogTone.Neutral then mainFrame.Style = Enum.FrameStyle.ChatBlue mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png" elseif tone == Enum.DialogTone.Friendly then mainFrame.Style = Enum.FrameStyle.ChatGreen mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botGreen_tailRight.png" elseif tone == Enum.DialogTone.Enemy then mainFrame.Style = Enum.FrameStyle.ChatRed mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botRed_tailRight.png" end styleChoices(tone) end function setChatNotificationTone(gui, purpose, tone) if tone == Enum.DialogTone.Neutral then gui.Image.Image = "rbxasset://textures/chatBubble_botBlue_notify_bkg.png" elseif tone == Enum.DialogTone.Friendly then gui.Image.Image = "rbxasset://textures/chatBubble_botGreen_notify_bkg.png" elseif tone == Enum.DialogTone.Enemy then gui.Image.Image = "rbxasset://textures/chatBubble_botRed_notify_bkg.png" end if purpose == Enum.DialogPurpose.Quest then gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_bang.png" elseif purpose == Enum.DialogPurpose.Help then gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_question.png" elseif purpose == Enum.DialogPurpose.Shop then gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_money.png" end end function createMessageDialog() messageDialog = Instance.new("Frame"); messageDialog.Name = "DialogScriptMessage" messageDialog.Style = Enum.FrameStyle.RobloxRound messageDialog.Visible = false local text = Instance.new("TextLabel") text.Name = "Text" text.Position = UDim2.new(0,0,0,-1) text.Size = UDim2.new(1,0,1,0) text.FontSize = Enum.FontSize.Size14 text.BackgroundTransparency = 1 text.TextColor3 = Color3.new(1,1,1) text.Parent = messageDialog end function showMessage(msg, size) messageDialog.Text.Text = msg messageDialog.Size = UDim2.new(0,size,0,40) messageDialog.Position = UDim2.new(0.5, -size/2, 0.5, -40) messageDialog.Visible = true wait(2) messageDialog.Visible = false end function variableDelay(str) local length = math.min(string.len(str), 100) wait(0.75 + ((length/75) * 1.5)) end function resetColor(frame, tone) if tone == Enum.DialogTone.Neutral then frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255) frame.Number.TextColor3 = Color3.new(45/255, 142/255, 245/255) elseif tone == Enum.DialogTone.Friendly then frame.BackgroundColor3 = Color3.new(0/255, 77/255, 0/255) frame.Number.TextColor3 = Color3.new(0/255, 190/255, 0/255) elseif tone == Enum.DialogTone.Enemy then frame.BackgroundColor3 = Color3.new(140/255, 0/255, 0/255) frame.Number.TextColor3 = Color3.new(255/255,88/255, 79/255) end end function highlightColor(frame, tone) if tone == Enum.DialogTone.Neutral then frame.BackgroundColor3 = Color3.new(2/255, 108/255, 255/255) frame.Number.TextColor3 = Color3.new(1, 1, 1) elseif tone == Enum.DialogTone.Friendly then frame.BackgroundColor3 = Color3.new(0/255, 128/255, 0/255) frame.Number.TextColor3 = Color3.new(1, 1, 1) elseif tone == Enum.DialogTone.Enemy then frame.BackgroundColor3 = Color3.new(204/255, 0/255, 0/255) frame.Number.TextColor3 = Color3.new(1, 1, 1) end end function wanderDialog() print("Wander") mainFrame.Visible = false endDialog() showMessage(characterWanderedOffMessage, characterWanderedOffSize) end function timeoutDialog() print("Timeout") mainFrame.Visible = false endDialog() showMessage(conversationTimedOut, conversationTimedOutSize) end function normalEndDialog() print("Done") endDialog() end function endDialog() if currentAbortDialogScript then currentAbortDialogScript:Remove() currentAbortDialogScript = nil end local dialog = currentConversationDialog currentConversationDialog = nil if dialog and dialog.InUse then local reenableScript = reenableDialogScript:Clone() reenableScript.archivable = false reenableScript.Disabled = false reenableScript.Parent = dialog end for dialog, gui in pairs(dialogMap) do if dialog and gui then gui.Enabled = not dialog.InUse end end currentConversationPartner = nil end function sanitizeMessage(msg) if string.len(msg) == 0 then return "..." else return msg end end function selectChoice(choice) renewKillswitch(currentConversationDialog) --First hide the Gui mainFrame.Visible = false if choice == lastChoice then game.Chat:Chat(game.Players.LocalPlayer.Character, "Goodbye!", getChatColor(currentTone())) normalEndDialog() else local dialogChoice = choiceMap[choice] game.Chat:Chat(game.Players.LocalPlayer.Character, sanitizeMessage(dialogChoice.UserDialog), getChatColor(currentTone())) wait(1) --currentConversationDialog:SignalDialogChoiceSelected(player, dialogChoice) game.Chat:Chat(currentConversationPartner, sanitizeMessage(dialogChoice.ResponseDialog), getChatColor(currentTone())) variableDelay(dialogChoice.ResponseDialog) presentDialogChoices(currentConversationPartner, dialogChoice:GetChildren()) end end function newChoice(numberText) local frame = Instance.new("TextButton") frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255) frame.AutoButtonColor = false frame.BorderSizePixel = 0 frame.Text = "" frame.MouseEnter:connect(function() highlightColor(frame, currentTone()) end) frame.MouseLeave:connect(function() resetColor(frame, currentTone()) end) frame.MouseButton1Click:connect(function() selectChoice(frame) end) local number = Instance.new("TextLabel") number.Name = "Number" number.TextColor3 = Color3.new(127/255, 212/255, 255/255) number.Text = numberText number.FontSize = Enum.FontSize.Size14 number.BackgroundTransparency = 1 number.Position = UDim2.new(0,4,0,2) number.Size = UDim2.new(0,20,0,24) number.TextXAlignment = Enum.TextXAlignment.Left number.TextYAlignment = Enum.TextYAlignment.Top number.Parent = frame local prompt = Instance.new("TextLabel") prompt.Name = "UserPrompt" prompt.BackgroundTransparency = 1 prompt.TextColor3 = Color3.new(1,1,1) prompt.FontSize = Enum.FontSize.Size14 prompt.Position = UDim2.new(0,28, 0, 2) prompt.Size = UDim2.new(1,-32, 1, -4) prompt.TextXAlignment = Enum.TextXAlignment.Left prompt.TextYAlignment = Enum.TextYAlignment.Top prompt.TextWrap = true prompt.Parent = frame return frame end function initialize(parent) choices[1] = newChoice("1)") choices[2] = newChoice("2)") choices[3] = newChoice("3)") choices[4] = newChoice("4)") lastChoice = newChoice("5)") lastChoice.UserPrompt.Text = "Goodbye!" lastChoice.Size = UDim2.new(1,0,0,28) mainFrame = Instance.new("Frame") mainFrame.Name = "UserDialogArea" mainFrame.Size = UDim2.new(0, 350, 0, 200) mainFrame.Style = Enum.FrameStyle.ChatBlue mainFrame.Visible = false local imageLabel = Instance.new("ImageLabel") imageLabel.Name = "Tail" imageLabel.Size = UDim2.new(0,62,0,53) imageLabel.Position = UDim2.new(1,8,0.25) imageLabel.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png" imageLabel.BackgroundTransparency = 1 imageLabel.Parent = mainFrame for n, obj in pairs(choices) do obj.Parent = mainFrame end lastChoice.Parent = mainFrame mainFrame.Parent = parent end function presentDialogChoices(talkingPart, dialogChoices) if not currentConversationDialog then return end currentConversationPartner = talkingPart local sortedDialogChoices = {} for n, obj in pairs(dialogChoices) do if obj:IsA("DialogChoice") then table.insert(sortedDialogChoices, obj) end end table.sort(sortedDialogChoices, function(a,b) return a.Name < b.Name end) if #sortedDialogChoices == 0 then normalEndDialog() return end local pos = 1 local yPosition = 0 choiceMap = {} for n, obj in pairs(choices) do obj.Visible = false end for n, obj in pairs(sortedDialogChoices) do if pos <= #choices then --3 lines is the maximum, set it to that temporarily choices[pos].Size = UDim2.new(1, 0, 0, 24*3) choices[pos].UserPrompt.Text = obj.UserDialog local height = math.ceil(choices[pos].UserPrompt.TextBounds.Y/24)*24 choices[pos].Position = UDim2.new(0, 0, 0, yPosition) choices[pos].Size = UDim2.new(1, 0, 0, height) choices[pos].Visible = true choiceMap[choices[pos]] = obj yPosition = yPosition + height pos = pos + 1 end end lastChoice.Position = UDim2.new(0,0,0,yPosition) lastChoice.Number.Text = pos .. ")" mainFrame.Size = UDim2.new(0, 350, 0, yPosition+24+32) mainFrame.Position = UDim2.new(0,20,0.0, -mainFrame.Size.Y.Offset-20) styleMainFrame(currentTone()) mainFrame.Visible = true end function doDialog(dialog) while not Instance.Lock(dialog, player) do wait() end if dialog.InUse then Instance.Unlock(dialog) return else dialog.InUse = true Instance.Unlock(dialog) end currentConversationDialog = dialog game.Chat:Chat(dialog.Parent, dialog.InitialPrompt, getChatColor(dialog.Tone)) variableDelay(dialog.InitialPrompt) presentDialogChoices(dialog.Parent, dialog:GetChildren()) end function renewKillswitch(dialog) if currentAbortDialogScript then currentAbortDialogScript:Remove() currentAbortDialogScript = nil end currentAbortDialogScript = timeoutScript:Clone() currentAbortDialogScript.archivable = false currentAbortDialogScript.Disabled = false currentAbortDialogScript.Parent = dialog end function checkForLeaveArea() while currentConversationDialog do if currentConversationDialog.Parent and (player:DistanceFromCharacter(currentConversationDialog.Parent.Position) >= currentConversationDialog.ConversationDistance) then wanderDialog() end wait(1) end end function startDialog(dialog) if dialog.Parent and dialog.Parent:IsA("BasePart") then if player:DistanceFromCharacter(dialog.Parent.Position) >= dialog.ConversationDistance then showMessage(tooFarAwayMessage, tooFarAwaySize) return end for dialog, gui in pairs(dialogMap) do if dialog and gui then gui.Enabled = false end end renewKillswitch(dialog) delay(1, checkForLeaveArea) doDialog(dialog) end end function removeDialog(dialog) if dialogMap[dialog] then dialogMap[dialog]:Remove() dialogMap[dialog] = nil end if dialogConnections[dialog] then dialogConnections[dialog]:disconnect() dialogConnections[dialog] = nil end end function addDialog(dialog) if dialog.Parent then if dialog.Parent:IsA("BasePart") then local chatGui = chatNotificationGui:clone() chatGui.Enabled = not dialog.InUse chatGui.Adornee = dialog.Parent chatGui.Parent = game.Players.LocalPlayer.PlayerGui chatGui.Image.Button.MouseButton1Click:connect(function() startDialog(dialog) end) setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone) dialogMap[dialog] = chatGui dialogConnections[dialog] = dialog.Changed:connect(function(prop) if prop == "Parent" and dialog.Parent then --This handles the reparenting case, seperate from removal case removeDialog(dialog) addDialog(dialog) elseif prop == "InUse" then chatGui.Enabled = not currentConversationDialog and not dialog.InUse if dialog == currentConversationDialog then timeoutDialog() end elseif prop == "Tone" or prop == "Purpose" then setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone) end end) else -- still need to listen to parent changes even if current parent is not a BasePart dialogConnections[dialog] = dialog.Changed:connect(function(prop) if prop == "Parent" and dialog.Parent then --This handles the reparenting case, seperate from removal case removeDialog(dialog) addDialog(dialog) end end) end end end --[[function fetchScripts() local model = game:GetService("InsertService"):LoadAsset(39226062) if type(model) == "string" then -- load failed, lets try again wait(0.1) model = game:GetService("InsertService"):LoadAsset(39226062) end if type(model) == "string" then -- not going to work, lets bail return end waitForDialogChildrenMyLord(model,"TimeoutScript") timeoutScript = model.TimeoutScript waitForDialogChildrenMyLord(model,"ReenableDialogScript") reenableDialogScript = model.ReenableDialogScript end ]]-- function onLoad() waitForProperty(game.Players, "LocalPlayer") player = game.Players.LocalPlayer waitForProperty(player, "Character") --print("Fetching Scripts") --fetchScripts() --print("Creating Guis") createChatNotificationGui() waitForFaker(bois,"Dialogs") --print("Creating MessageDialog") createMessageDialog() messageDialog.Parent = game.Players.LocalPlayer.PlayerGui.Dialogs --print("Initializing Frame") local frame = Instance.new("Frame") frame.Name = "DialogFrame" frame.Position = UDim2.new(0,0,0,0) frame.Size = UDim2.new(0,0,0,0) frame.BackgroundTransparency = 1 frame.Parent = game.Players.LocalPlayer.PlayerGui.Dialogs.ControlFrame.BottomLeftControl initialize(frame) --print("Adding Dialogs") game.CollectionService.ItemAdded:connect(function(obj) if obj:IsA("Dialog") then addDialog(obj) end end) game.CollectionService.ItemRemoved:connect(function(obj) if obj:IsA("Dialog") then removeDialog(obj) end end) for i, obj in pairs(game.CollectionService:GetCollection("Dialog")) do if obj:IsA("Dialog") then addDialog(obj) end end end onLoad() Health false 4285215356 1 4279970357 1 false false tray 0.5 -44 1 -26 0 170 0 18 2 0 true 1 false 4294967295 1 4279970357 1 false false rbxasset://textures/healthgui/bkg.png bkg 0 0 0 0 1 0 1 0 0 true 1 false 4294967295 1 4279970357 1 false false rbxasset://textures/healthgui/BarRed.png barRed 0.0189999994 0 0.100000001 0 0 0 0 0 0 true 1 false 4294967295 1.00000012 4279970357 0 false false bar2 0.0189999994 0 0.100000001 0 0.192000002 0 0.829999983 0 0 0 true 1 false Init h = game.Players.LocalPlayer.Character.Humanoid tray = script.Parent.Parent base = tray.Parent local lastHealth = 100 local lastHealth2 = 100 local maxWidth = 0.96 function UpdateGUI(health) local width = (health / h.MaxHealth) * maxWidth local height = 0.83 local lastX = tray.bar.Position.X.Scale local x = 0.019 + (maxWidth - width) local y = 0.1 tray.bar.Position = UDim2.new(x,0,y, 0) tray.bar.Size = UDim2.new(width, 0, height, 0) -- If more than 1/4 health, bar = green. Else, bar = red. if( (health / h.MaxHealth) > 0.25 ) then tray.barRed.Size = UDim2.new(0, 0, 0, 0) else tray.barRed.Position = tray.bar.Position tray.barRed.Size = tray.bar.Size tray.bar.Size = UDim2.new(0, 0, 0, 0) end if ( (lastHealth - health) > (h.MaxHealth / 10) ) then lastHealth = health if h.Health ~= h.MaxHealth then delay(0,function() AnimateHurtOverlay() end) delay(0,function() AnimateBars(x, y, lastX, height) end) end else lastHealth = health end end function AnimateBars(x, y, lastX, height) local width = math.abs(x - lastX) if( x > lastX ) then x = lastX end tray.bar2.Position = UDim2.new(x,0, y, 0) tray.bar2.Size = UDim2.new(width, 0, height, 0) tray.bar2.BackgroundTransparency = 0 local GBchannels = 1 local j = 0.2 local i_total = 30 for i=1,i_total do -- Increment Values if (GBchannels < 0.2) then j = -j end GBchannels = GBchannels + j if (i > (i_total - 10)) then tray.bar2.BackgroundTransparency = tray.bar2.BackgroundTransparency + 0.1 end tray.bar2.BackgroundColor3 = Color3.new(1, GBchannels, GBchannels) wait(0.02) end end function AnimateHurtOverlay() -- Start: -- overlay.Position = UDim2.new(0, 0, 0, -22) -- overlay.Size = UDim2.new(1, 0, 1.15, 30) -- Finish: -- overlay.Position = UDim2.new(-2, 0, -2, -22) -- overlay.Size = UDim2.new(4.5, 0, 4.65, 30) overlay = base.hurtOverlay overlay.Visible = true overlay.Position = UDim2.new(-2, 0, -2, -22) overlay.Size = UDim2.new(4.5, 0, 4.65, 30) -- Animate In, fast local i_total = 2 local wiggle_total = 0 local wiggle_i = 0.02 for i=1,i_total do overlay.Position = UDim2.new( (-2 + (2 * (i/i_total)) + wiggle_total/2), 0, (-2 + (2 * (i/i_total)) + wiggle_total/2), -22 ) overlay.Size = UDim2.new( (4.5 - (3.5 * (i/i_total)) + wiggle_total), 0, (4.65 - (3.5 * (i/i_total)) + wiggle_total), 30 ) wait(0.01) end i_total = 30 wait(0.03) -- Animate Out, slow for i=1,i_total do if( math.abs(wiggle_total) > (wiggle_i * 3) ) then wiggle_i = -wiggle_i end wiggle_total = wiggle_total + wiggle_i overlay.Position = UDim2.new( (0 - (2 * (i/i_total)) + wiggle_total/2), 0, (0 - (2 * (i/i_total)) + wiggle_total/2), -22 ) overlay.Size = UDim2.new( (1 + (3.5 * (i/i_total)) + wiggle_total), 0, (1.15 + (3.5 * (i/i_total)) + wiggle_total), 30 ) wait(0.01) end -- Hide after we're done overlay.Position = UDim2.new(10, 0, 0, 0) overlay.Visible = false end h.Changed:connect(function() UpdateGUI(h.Health) if ( (lastHealth2 - h.Health) > (h.MaxHealth / 10) ) then lastHealth2 = h.Health else lastHealth2 = h.Health end end) false 4294967295 1 4279970357 1 false false rbxasset://textures/healthgui/Bar.png bar 0.0189999994 0 0.100000001 0 0.959999979 0 0.829999983 0 0 true 1 false 4294967295 1 4279970357 0 false false rbxasset://textures/healthgui/label.png label 0.680000007 0 0.300000012 0 0.25 0 0.349999994 0 0 true 1 false 4290164919 1 4279970357 1 false false rbxasset://textures/healthgui/HurtOverlay.png hurtOverlay 2 0 0 -22 1 0 1.1500001 30 0 false 1 false Hide while true do game.Players.LocalPlayer.PlayerGui.HealthGUI.tray.Visible = false game.Players.LocalPlayer.PlayerGui.HealthGUI.hurtOverlay.Visible = false end Menu false 4288914085 1 4279970357 1 false false ControlFrame 0 0 0 0 1 0 1 0 0 0 true 1 false 4288914085 1 4279970357 1 false false BottomLeftControl 0 0 1 -46 0 130 0 46 0 0 true 1 true true 4288914085 1 4279970357 1 false false rbxasset://textures/Exit.png false Exit 0 2 0 -2 false 0 56 0 41 0 0 false 1 false 4288914085 1 4279970357 1 false false BottomRightControl 1 -180 1 -41 0 180 0 41 0 0 true 1 false 4288914085 1 4279970357 1 false false TopLeftControl 0 0 0 0 0.0500000007 0 0.0500000007 0 0 0 true 1 false 4288914085 1 4279970357 1 false false NotificationBox 1 -200 0.5 0 0 200 0.419999987 0 0 true 1 false Workaround game.Players.LocalPlayer.PlayerGui.Menu.MenuScript.Disabled = true game.Players.LocalPlayer.PlayerGui.Menu.MenuScript.Disabled = false false MenuScript -- fixed by iago#6808 -- -- version 0.25 -- -- changelog: -- -- 100% finished settings menu -- -- report abuse is still in work -- local t = {} local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc) local eventConnection = nil --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away) local tryConnect = function() if game:IsAncestorOf(parentInstance) then --Entering the world, make sure we are connected/synced if not eventConnection then eventConnection = instance[event]:connect(signalFunc) if syncFunc then syncFunc() end end else --Probably leaving the world, so disconnect for now if eventConnection then eventConnection:disconnect() if removeFunc then removeFunc() end end end end --Hook it up to ancestryChanged signal local connection = parentInstance.AncestryChanged:connect(tryConnect) --Now connect us if we're already in the world tryConnect() return connection end local function getScreenGuiAncestor(instance) local localInstance = instance while localInstance and not localInstance:IsA("ScreenGui") do localInstance = localInstance.Parent end return localInstance end local function CreateButtons(frame, buttons, yPos, ySize) local buttonNum = 1 local buttonObjs = {} for i, obj in ipairs(buttons) do local button = Instance.new("TextButton") button.Name = "Button" .. buttonNum button.Font = Enum.Font.Arial button.FontSize = Enum.FontSize.Size18 button.AutoButtonColor = true button.Modal = true if obj["Style"] then button.Style = obj.Style else button.Style = Enum.ButtonStyle.RobloxButton end if obj["ZIndex"] then button.ZIndex = obj.ZIndex end button.Text = obj.Text button.TextColor3 = Color3.new(1,1,1) button.MouseButton1Click:connect(obj.Function) button.Parent = frame buttonObjs[buttonNum] = button buttonNum = buttonNum + 1 end local numButtons = buttonNum-1 if numButtons == 1 then frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset) elseif numButtons == 2 then frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset) frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset) frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset) elseif numButtons >= 3 then local spacing = .1 / numButtons local buttonSize = .9 / numButtons buttonNum = 1 while buttonNum <= numButtons do buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset) buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset) buttonNum = buttonNum + 1 end end end local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps) local steps = 10 local newStep = steps - 1 --otherwise we really get one more step than we want local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X )) local wholeNum, remainder = math.modf(relativePosX * newStep) if remainder > 0.5 then wholeNum = wholeNum + 1 end relativePosX = wholeNum/newStep local result = math.ceil(relativePosX * newStep) if sliderPosition.Value ~= (result + 1) then --only update if we moved a step sliderPosition.Value = result + 1 slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end end local function cancelSlide(areaSoak) areaSoak.Visible = false if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end end t.CreateStyledMessageDialog = function(title, message, style, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0, 165) frame.Position = UDim2.new(0.25, 0, 0.5, -72.5) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local styleImage = Instance.new("ImageLabel") styleImage.Name = "StyleImage" styleImage.BackgroundTransparency = 1 styleImage.Position = UDim2.new(0,5,0,15) if style == "error" or style == "Error" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42565285" elseif style == "notify" or style == "Notify" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42604978" elseif style == "confirm" or style == "Confirm" then styleImage.Size = UDim2.new(0, 74, 0, 76) styleImage.Image = "http://www.roblox.com/asset/?id=42557901" else return t.CreateMessageDialog(title,message,buttons) end styleImage.Parent = frame local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.TextStrokeTransparency = 0 titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 80, 0, 0) titleLabel.Size = UDim2.new(1, -80, 0, 40) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextStrokeTransparency = 0 messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 80, 0, 45) messageLabel.Size = UDim2.new(0.95, -80, 0, 55) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) ) return frame end t.CreateMessageDialog = function(title, message, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0.5, 0) frame.Position = UDim2.new(0.25, 0, 0.25, 0) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 0, 0, 0) titleLabel.Size = UDim2.new(1, 0, 0.15, 0) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0) messageLabel.Size = UDim2.new(0.95, 0, .55, 0) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0)) return frame end t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ) local baseZIndex = 0 if (type(baseZ) == "number") then baseZIndex = baseZ end local width = UDim.new(0, 100) local height = UDim.new(0, 32) local xPos = 0.055 local frame = Instance.new("Frame") local textColor = Color3.new(1,1,1) if (whiteSkin) then textColor = Color3.new(0.5, 0.5, 0.5) end frame.Name = "DropDownMenu" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(width, height) local dropDownMenu = Instance.new("TextButton") dropDownMenu.Name = "DropDownMenuButton" dropDownMenu.TextWrap = true dropDownMenu.TextColor3 = textColor dropDownMenu.Text = "Choose One" dropDownMenu.Font = Enum.Font.ArialBold dropDownMenu.FontSize = Enum.FontSize.Size18 dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center dropDownMenu.BackgroundTransparency = 1 dropDownMenu.AutoButtonColor = true if (whiteSkin) then dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else dropDownMenu.Style = Enum.ButtonStyle.RobloxButton end dropDownMenu.Size = UDim2.new(1,0,1,0) dropDownMenu.Parent = frame dropDownMenu.ZIndex = 2 + baseZIndex local dropDownIcon = Instance.new("ImageLabel") dropDownIcon.Name = "Icon" dropDownIcon.Active = false if (whiteSkin) then dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png" dropDownIcon.Size = UDim2.new(0,16,0,12) dropDownIcon.Position = UDim2.new(1,-17,0.5, -6) else dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894" dropDownIcon.Size = UDim2.new(0,11,0,6) dropDownIcon.Position = UDim2.new(1,-11,0.5, -2) end dropDownIcon.BackgroundTransparency = 1 dropDownIcon.Parent = dropDownMenu dropDownIcon.ZIndex = 2 + baseZIndex local itemCount = #items local dropDownItemCount = #items local useScrollButtons = false if dropDownItemCount > 6 then useScrollButtons = true dropDownItemCount = 6 end local droppedDownMenu = Instance.new("TextButton") droppedDownMenu.Name = "List" droppedDownMenu.Text = "" droppedDownMenu.BackgroundTransparency = 1 --droppedDownMenu.AutoButtonColor = true if (whiteSkin) then droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton end droppedDownMenu.Visible = false droppedDownMenu.Active = true --Blocks clicks droppedDownMenu.Position = UDim2.new(0,0,0,0) droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0) droppedDownMenu.Parent = frame droppedDownMenu.ZIndex = 2 + baseZIndex local choiceButton = Instance.new("TextButton") choiceButton.Name = "ChoiceButton" choiceButton.BackgroundTransparency = 1 choiceButton.BorderSizePixel = 0 choiceButton.Text = "ReplaceMe" choiceButton.TextColor3 = textColor choiceButton.TextXAlignment = Enum.TextXAlignment.Left choiceButton.TextYAlignment = Enum.TextYAlignment.Center choiceButton.BackgroundColor3 = Color3.new(1, 1, 1) choiceButton.Font = Enum.Font.Arial choiceButton.FontSize = Enum.FontSize.Size18 if useScrollButtons then choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0) else choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0) end choiceButton.TextWrap = true choiceButton.ZIndex = 2 + baseZIndex local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = true areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 3 + baseZIndex local dropDownSelected = false local scrollUpButton local scrollDownButton local scrollMouseCount = 0 local setZIndex = function(baseZIndex) droppedDownMenu.ZIndex = baseZIndex +1 if scrollUpButton then scrollUpButton.ZIndex = baseZIndex + 3 end if scrollDownButton then scrollDownButton.ZIndex = baseZIndex + 3 end local children = droppedDownMenu:GetChildren() if children then for i, child in ipairs(children) do if child.Name == "ChoiceButton" then child.ZIndex = baseZIndex + 2 elseif child.Name == "ClickCaptureButton" then child.ZIndex = baseZIndex end end end end local scrollBarPosition = 1 local updateScroll = function() if scrollUpButton then scrollUpButton.Active = scrollBarPosition > 1 end if scrollDownButton then scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount end local children = droppedDownMenu:GetChildren() if not children then return end local childNum = 1 for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then obj.Visible = false else obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0) obj.Visible = true end obj.TextColor3 = textColor obj.BackgroundTransparency = 1 childNum = childNum + 1 end end end local toggleVisibility = function() dropDownSelected = not dropDownSelected areaSoak.Visible = not areaSoak.Visible dropDownMenu.Visible = not dropDownSelected droppedDownMenu.Visible = dropDownSelected if dropDownSelected then setZIndex(4 + baseZIndex) else setZIndex(2 + baseZIndex) end if useScrollButtons then updateScroll() end end droppedDownMenu.MouseButton1Click:connect(toggleVisibility) local updateSelection = function(text) local foundItem = false local children = droppedDownMenu:GetChildren() local childNum = 1 if children then for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if obj.Text == text then obj.Font = Enum.Font.ArialBold foundItem = true scrollBarPosition = childNum if (whiteSkin) then obj.TextColor3 = Color3.new(90/255,142/255,233/255) end else obj.Font = Enum.Font.Arial if (whiteSkin) then obj.TextColor3 = textColor end end childNum = childNum + 1 end end end if not text then dropDownMenu.Text = "Choose One" scrollBarPosition = 1 else if not foundItem then error("Invalid Selection Update -- " .. text) end if scrollBarPosition + dropDownItemCount > itemCount + 1 then scrollBarPosition = itemCount - dropDownItemCount + 1 end dropDownMenu.Text = text end end local function scrollDown() if scrollBarPosition + dropDownItemCount <= itemCount then scrollBarPosition = scrollBarPosition + 1 updateScroll() return true end return false end local function scrollUp() if scrollBarPosition > 1 then scrollBarPosition = scrollBarPosition - 1 updateScroll() return true end return false end if useScrollButtons then --Make some scroll buttons scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0) scrollUpButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollUp() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollUp() == false then break end wait(0.1) end end) scrollUpButton.Parent = droppedDownMenu scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) scrollDownButton.Position = UDim2.new(1,-11,1,-11) scrollDownButton.Parent = droppedDownMenu scrollDownButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollDown() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollDown() == false then break end wait(0.1) end end) local scrollbar = Instance.new("ImageLabel") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4) scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2) scrollbar.Parent = droppedDownMenu end for i,item in ipairs(items) do -- needed to maintain local scope for items in event listeners below local button = choiceButton:clone() if forRoblox then end button.Text = item button.Parent = droppedDownMenu if (whiteSkin) then button.TextColor3 = textColor end button.MouseButton1Click:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 updateSelection(item) onSelect(item) toggleVisibility() end) button.MouseEnter:connect(function() --Add Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(0,0,0) end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 end) end --This does the initial layout of the buttons updateScroll() frame.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(frame) end end) dropDownMenu.MouseButton1Click:connect(toggleVisibility) areaSoak.MouseButton1Click:connect(toggleVisibility) return frame, updateSelection end t.CreatePropertyDropDownMenu = function(instance, property, enum) local items = enum:GetEnumItems() local names = {} local nameToItem = {} for i,obj in ipairs(items) do names[i] = obj.Name nameToItem[obj.Name] = obj end local frame local updateSelection frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end) ScopedConnect(frame, instance, "Changed", function(prop) if prop == property then updateSelection(instance[property].Name) end end, function() updateSelection(instance[property].Name) end) return frame end t.GetFontHeight = function(font, fontSize) if font == nil or fontSize == nil then error("Font and FontSize must be non-nil") end if font == Enum.Font.Legacy then if fontSize == Enum.FontSize.Size8 then return 12 elseif fontSize == Enum.FontSize.Size9 then return 14 elseif fontSize == Enum.FontSize.Size10 then return 15 elseif fontSize == Enum.FontSize.Size11 then return 17 elseif fontSize == Enum.FontSize.Size12 then return 18 elseif fontSize == Enum.FontSize.Size14 then return 21 elseif fontSize == Enum.FontSize.Size18 then return 27 elseif fontSize == Enum.FontSize.Size24 then return 36 elseif fontSize == Enum.FontSize.Size36 then return 54 elseif fontSize == Enum.FontSize.Size48 then return 72 else error("Unknown FontSize") end elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then if fontSize == Enum.FontSize.Size8 then return 8 elseif fontSize == Enum.FontSize.Size9 then return 9 elseif fontSize == Enum.FontSize.Size10 then return 10 elseif fontSize == Enum.FontSize.Size11 then return 11 elseif fontSize == Enum.FontSize.Size12 then return 12 elseif fontSize == Enum.FontSize.Size14 then return 14 elseif fontSize == Enum.FontSize.Size18 then return 18 elseif fontSize == Enum.FontSize.Size24 then return 24 elseif fontSize == Enum.FontSize.Size36 then return 36 elseif fontSize == Enum.FontSize.Size48 then return 48 else error("Unknown FontSize") end else error("Unknown Font " .. font) end end local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable) local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y for i, child in ipairs(guiObjects) do if child:IsA("TextLabel") or child:IsA("TextButton") then local isLabel = child:IsA("TextLabel") if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining) if child.TextFits and child.TextBounds.Y < pixelsRemaining then child.Visible = true if isLabel then child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"]) else child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"]) end while not child.TextFits do child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1) end pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end else child.Visible = false pixelsRemaining = -1 end else --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y child.Visible = (pixelsRemaining >= 0) end end end t.LayoutGuiObjects = function(frame, guiObjects, settingsTable) if not frame:IsA("GuiObject") then error("Frame must be a GuiObject") end for i, child in ipairs(guiObjects) do if not child:IsA("GuiObject") then error("All elements that are layed out must be of type GuiObject") end end if not settingsTable then settingsTable = {} end if not settingsTable["TextLabelSizePadY"] then settingsTable["TextLabelSizePadY"] = 0 end if not settingsTable["TextLabelPositionPadY"] then settingsTable["TextLabelPositionPadY"] = 0 end if not settingsTable["TextButtonSizePadY"] then settingsTable["TextButtonSizePadY"] = 12 end if not settingsTable["TextButtonPositionPadY"] then settingsTable["TextButtonPositionPadY"] = 2 end --Wrapper frame takes care of styled objects local wrapperFrame = Instance.new("Frame") wrapperFrame.Name = "WrapperFrame" wrapperFrame.BackgroundTransparency = 1 wrapperFrame.Size = UDim2.new(1,0,1,0) wrapperFrame.Parent = frame for i, child in ipairs(guiObjects) do child.Parent = wrapperFrame end local recalculate = function() wait() layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(recalculate) layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end t.CreateSlider = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 4 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local bar = Instance.new("TextButton") bar.Text = "" bar.AutoButtonColor = false bar.Name = "Bar" bar.BackgroundColor3 = Color3.new(0,0,0) if type(width) == "number" then bar.Size = UDim2.new(0,width,0,5) else bar.Size = UDim2.new(0,200,0,5) end bar.BorderColor3 = Color3.new(95/255,95/255,95/255) bar.ZIndex = 2 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/Slider.png" slider.Position = UDim2.new(0,0,0.5,-10) slider.Size = UDim2.new(0,20,0,20) slider.ZIndex = 3 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,10) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(10, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (10 - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateSliderNew = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 6 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local sliderBarImgHeight = 7 local sliderBarCapImgWidth = 4 local bar = Instance.new("ImageButton") bar.BackgroundTransparency = 1 bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png" bar.Name = "Bar" local displayWidth = 200 if type(width) == "number" then bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight) displayWidth = width - (sliderBarCapImgWidth * 2) else bar.Size = UDim2.new(0,200,0,sliderBarImgHeight) end bar.ZIndex = 3 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local barLeft = bar:clone() barLeft.Name = "BarLeft" barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png" barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight) barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset) barLeft.Parent = sliderGui barLeft.ZIndex = 3 local barRight = barLeft:clone() barRight.Name = "BarRight" barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png" barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset) barRight.Parent = sliderGui local fillLeft = barLeft:clone() fillLeft.Name = "FillLeft" fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png" fillLeft.Parent = sliderGui fillLeft.ZIndex = 4 local fill = fillLeft:clone() fill.Name = "Fill" fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png" fill.Parent = bar fill.ZIndex = 4 fill.Position = UDim2.new(0, 0, 0, 0) fill.Size = UDim2.new(0.5, 0, 1, 0) -- bar.Visible = false local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/slider_new_tab.png" slider.Position = UDim2.new(0,0,0.5,-14) slider.Size = UDim2.new(0,28,0,28) slider.ZIndex = 5 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (steps - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) fill.Size = UDim2.new(relativePosX, 0, 1, 0) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateTrueScrollingFrame = function() local lowY = nil local highY = nil local dragCon = nil local upCon = nil local internalChange = false local descendantsChangeConMap = {} local scrollingFrame = Instance.new("Frame") scrollingFrame.Name = "ScrollingFrame" scrollingFrame.Active = true scrollingFrame.Size = UDim2.new(1,0,1,0) scrollingFrame.ClipsDescendants = true local controlFrame = Instance.new("Frame") controlFrame.Name = "ControlFrame" controlFrame.BackgroundTransparency = 1 controlFrame.Size = UDim2.new(0,18,1,0) controlFrame.Position = UDim2.new(1,-20,0,0) controlFrame.Parent = scrollingFrame local scrollBottom = Instance.new("BoolValue") scrollBottom.Value = false scrollBottom.Name = "ScrollBottom" scrollBottom.Parent = controlFrame local scrollUp = Instance.new("BoolValue") scrollUp.Value = false scrollUp.Name = "scrollUp" scrollUp.Parent = controlFrame local scrollUpButton = Instance.new("TextButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.Text = "" scrollUpButton.AutoButtonColor = false scrollUpButton.BackgroundColor3 = Color3.new(0,0,0) scrollUpButton.BorderColor3 = Color3.new(1,1,1) scrollUpButton.BackgroundTransparency = 0.5 scrollUpButton.Size = UDim2.new(0,18,0,18) scrollUpButton.ZIndex = 2 scrollUpButton.Parent = controlFrame for i = 1, 6 do local triFrame = Instance.new("Frame") triFrame.BorderColor3 = Color3.new(1,1,1) triFrame.Name = "tri" .. tostring(i) triFrame.ZIndex = 3 triFrame.BackgroundTransparency = 0.5 triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0) triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1)) triFrame.Parent = scrollUpButton end scrollUpButton.MouseEnter:connect(function() scrollUpButton.BackgroundTransparency = 0.1 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.1 end end) scrollUpButton.MouseLeave:connect(function() scrollUpButton.BackgroundTransparency = 0.5 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.5 end end) local scrollDownButton = scrollUpButton:clone() scrollDownButton.Name = "ScrollDownButton" scrollDownButton.Position = UDim2.new(0,0,1,-18) local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1)) end scrollDownButton.MouseEnter:connect(function() scrollDownButton.BackgroundTransparency = 0.1 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.1 end end) scrollDownButton.MouseLeave:connect(function() scrollDownButton.BackgroundTransparency = 0.5 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.5 end end) scrollDownButton.Parent = controlFrame local scrollTrack = Instance.new("Frame") scrollTrack.Name = "ScrollTrack" scrollTrack.BackgroundTransparency = 1 scrollTrack.Size = UDim2.new(0,18,1,-38) scrollTrack.Position = UDim2.new(0,0,0,19) scrollTrack.Parent = controlFrame local scrollbar = Instance.new("TextButton") scrollbar.BackgroundColor3 = Color3.new(0,0,0) scrollbar.BorderColor3 = Color3.new(1,1,1) scrollbar.BackgroundTransparency = 0.5 scrollbar.AutoButtonColor = false scrollbar.Text = "" scrollbar.Active = true scrollbar.Name = "ScrollBar" scrollbar.ZIndex = 2 scrollbar.BackgroundTransparency = 0.5 scrollbar.Size = UDim2.new(0, 18, 0.1, 0) scrollbar.Position = UDim2.new(0,0,0,0) scrollbar.Parent = scrollTrack local scrollNub = Instance.new("Frame") scrollNub.Name = "ScrollNub" scrollNub.BorderColor3 = Color3.new(1,1,1) scrollNub.Size = UDim2.new(0,10,0,0) scrollNub.Position = UDim2.new(0.5,-5,0.5,0) scrollNub.ZIndex = 2 scrollNub.BackgroundTransparency = 0.5 scrollNub.Parent = scrollbar local newNub = scrollNub:clone() newNub.Position = UDim2.new(0.5,-5,0.5,-2) newNub.Parent = scrollbar local lastNub = scrollNub:clone() lastNub.Position = UDim2.new(0.5,-5,0.5,2) lastNub.Parent = scrollbar scrollbar.MouseEnter:connect(function() scrollbar.BackgroundTransparency = 0.1 scrollNub.BackgroundTransparency = 0.1 newNub.BackgroundTransparency = 0.1 lastNub.BackgroundTransparency = 0.1 end) scrollbar.MouseLeave:connect(function() scrollbar.BackgroundTransparency = 0.5 scrollNub.BackgroundTransparency = 0.5 newNub.BackgroundTransparency = 0.5 lastNub.BackgroundTransparency = 0.5 end) local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local function positionScrollBar(x,y,offset) local oldPos = scrollbar.Position if y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) return (oldPos ~= scrollbar.Position) end local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) return (oldPos ~= scrollbar.Position) end local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y if newScaleYPos + relativeSize > 1 then newScaleYPos = 1 - relativeSize scrollBottom.Value = true scrollUp.Value = false elseif newScaleYPos <= 0 then newScaleYPos = 0 scrollUp.Value = true scrollBottom.Value = false else scrollUp.Value = false scrollBottom.Value = false end scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0) return (oldPos ~= scrollbar.Position) end local function drillDownSetHighLow(instance) if not instance or not instance:IsA("GuiObject") then return end if instance == controlFrame then return end if instance:IsDescendantOf(controlFrame) then return end if not instance.Visible then return end if lowY and lowY > instance.AbsolutePosition.Y then lowY = instance.AbsolutePosition.Y elseif not lowY then lowY = instance.AbsolutePosition.Y end if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end local children = instance:GetChildren() for i = 1, #children do drillDownSetHighLow(children[i]) end end local function resetHighLow() local firstChildren = scrollingFrame:GetChildren() for i = 1, #firstChildren do drillDownSetHighLow(firstChildren[i]) end end local function recalculate() internalChange = true local percentFrame = 0 if scrollbar.Position.Y.Scale > 0 then if scrollbar.Visible then percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y) else percentFrame = 0 end end if percentFrame > 0.99 then percentFrame = 1 end local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame local guiChildren = scrollingFrame:GetChildren() for i = 1, #guiChildren do if guiChildren[i] ~= controlFrame then guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset, 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount) end end lowY = nil highY = nil resetHighLow() internalChange = false end local function setSliderSizeAndPosition() if not highY or not lowY then return end local totalYSpan = math.abs(highY - lowY) if totalYSpan == 0 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end return end local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan if percentShown >= 1 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false recalculate() else scrollbar.Visible = true scrollDownButton.Visible = true scrollUpButton.Visible = true scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0) end local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2) if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) end if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) end end local buttonScrollAmountPixels = 7 local reentrancyGuardScrollUp = false local function doScrollUp() if reentrancyGuardScrollUp then return end reentrancyGuardScrollUp = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollUp = false end local reentrancyGuardScrollDown = false local function doScrollDown() if reentrancyGuardScrollDown then return end reentrancyGuardScrollDown = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollDown = false end local function scrollUp(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local function scrollDown(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end scrollbar.MouseButton1Down:connect(function(x,y) if scrollbar.Active then scrollStamp = tick() local mouseOffset = y - scrollbar.AbsolutePosition.y if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end local prevY = y local reentrancyGuardMouseScroll = false dragCon = mouseDrag.MouseMoved:connect(function(x,y) if reentrancyGuardMouseScroll then return end reentrancyGuardMouseScroll = true if positionScrollBar(x,y,mouseOffset) then recalculate() end reentrancyGuardMouseScroll = false end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect(function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect(function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) local function heightCheck(instance) if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end setSliderSizeAndPosition() end local function highLowRecheck() local oldLowY = lowY local oldHighY = highY lowY = nil highY = nil resetHighLow() if (lowY ~= oldLowY) or (highY ~= oldHighY) then setSliderSizeAndPosition() end end local function descendantChanged(this, prop) if internalChange then return end if not this.Visible then return end if prop == "Size" or prop == "Position" then wait() highLowRecheck() end end scrollingFrame.DescendantAdded:connect(function(instance) if not instance:IsA("GuiObject") then return end if instance.Visible then wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end) end) scrollingFrame.DescendantRemoving:connect(function(instance) if not instance:IsA("GuiObject") then return end if descendantsChangeConMap[instance] then descendantsChangeConMap[instance]:disconnect() descendantsChangeConMap[instance] = nil end wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end) scrollingFrame.Changed:connect(function(prop) if prop == "AbsoluteSize" then if not highY or not lowY then return end highLowRecheck() setSliderSizeAndPosition() end end) return scrollingFrame, controlFrame end t.CreateScrollingFrame = function(orderList,scrollStyle) local frame = Instance.new("Frame") frame.Name = "ScrollingFrame" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1,0,1,0) local scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) local scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) local scrollbar = Instance.new("ImageButton") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, 0, 150) local scrollStamp = 0 local scrollDrag = Instance.new("ImageButton") scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186" scrollDrag.Size = UDim2.new(1, 0, 0, 16) scrollDrag.BackgroundTransparency = 1 scrollDrag.Name = "ScrollDrag" scrollDrag.Active = true scrollDrag.Parent = scrollbar local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local style = "simple" if scrollStyle and tostring(scrollStyle) then style = scrollStyle end local scrollPosition = 1 local rowSize = 0 local howManyDisplayed = 0 local layoutGridScrollBar = function() howManyDisplayed = 0 local guiObjects = {} if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end if scrollPosition < 1 then scrollPosition = 1 end local totalPixelsY = frame.AbsoluteSize.Y local pixelsRemainingY = frame.AbsoluteSize.Y local totalPixelsX = frame.AbsoluteSize.X local xCounter = 0 local rowSizeCounter = 0 local setRowSize = true local pixelsBelowScrollbar = 0 local pos = #guiObjects local currentRowY = 0 pos = scrollPosition --count up from current scroll position to fill out grid while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X --previous pos was the end of a row if xCounter >= totalPixelsX then pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 xCounter = guiObjects[pos].AbsoluteSize.X end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos + 1 end --Count wherever current row left off pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 pos = scrollPosition - 1 xCounter = 0 --objects with varying X,Y dimensions can rarely cause minor errors --rechecking every new scrollPosition is necessary to avoid 100% of errors --count backwards from current scrollPosition to see if we can add more rows while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X rowSizeCounter = rowSizeCounter + 1 if xCounter >= totalPixelsX then rowSize = rowSizeCounter - 1 rowSizeCounter = 0 xCounter = guiObjects[pos].AbsoluteSize.X if pixelsBelowScrollbar + currentRowY <= totalPixelsY then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY if scrollPosition <= rowSize then scrollPosition = 1 break else scrollPosition = scrollPosition - rowSize end currentRowY = 0 else break end end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos - 1 end --Do check last time if pos = 0 if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then scrollPosition = 1 end xCounter = 0 --pos = scrollPosition rowSizeCounter = 0 setRowSize = true local lastChildSize = 0 local xOffset,yOffset = 0 if guiObjects[1] then yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2) xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2) end for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemainingY < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject if setRowSize then rowSizeCounter = rowSizeCounter + 1 end if xCounter + child.AbsoluteSize.X >= totalPixelsX then if setRowSize then rowSize = rowSizeCounter - 1 setRowSize = false end xCounter = 0 pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y end child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset) xCounter = xCounter + child.AbsoluteSize.X child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0) if child.Visible then howManyDisplayed = howManyDisplayed + 1 end lastChildSize = child.AbsoluteSize end end end scrollUpButton.Active = (scrollPosition > 1) if lastChildSize == 0 then scrollDownButton.Active = false else scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0) end scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local layoutSimpleScrollBar = function() local guiObjects = {} howManyDisplayed = 0 if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y local pixelsBelowScrollbar = 0 local pos = #guiObjects while pixelsBelowScrollbar < totalPixels and pos >= 1 do if pos >= scrollPosition then pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y else if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y if scrollPosition <= 1 then scrollPosition = 1 break else --local ("Backing up ScrollPosition from -- " ..scrollPosition) scrollPosition = scrollPosition - 1 end else break end end pos = pos - 1 end pos = scrollPosition for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemaining < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if (pixelsRemaining >= 0) then child.Visible = true howManyDisplayed = howManyDisplayed + 1 else child.Visible = false end end end end scrollUpButton.Active = (scrollPosition > 1) scrollDownButton.Active = (pixelsRemaining < 0) scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local moveDragger = function() local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end if not scrollDrag.Parent then return end local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1)) if dragSizeY < 16 then dragSizeY = 16 end scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY) local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed)) if relativeYPos > 1 then relativeYPos = 1 elseif relativeYPos < 0 then relativeYPos = 0 end local absYPos = 0 if relativeYPos ~= 0 then absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y) end scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos) end local reentrancyGuard = false local recalculate = function() if reentrancyGuard then return end reentrancyGuard = true wait() local success, err = nil if style == "grid" then success, err = pcall(function() layoutGridScrollBar() end) elseif style == "simple" then success, err = pcall(function() layoutSimpleScrollBar() end) end if not success then print(err) end moveDragger() reentrancyGuard = false end local doScrollUp = function() scrollPosition = (scrollPosition) - rowSize if scrollPosition < 1 then scrollPosition = 1 end recalculate(nil) end local doScrollDown = function() scrollPosition = (scrollPosition) + rowSize recalculate(nil) end local scrollUp = function(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local scrollDown = function(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local y = 0 scrollDrag.MouseButton1Down:connect(function(x,y) if scrollDrag.Active then scrollStamp = tick() local mouseOffset = y - scrollDrag.AbsolutePosition.y local dragCon local upCon dragCon = mouseDrag.MouseMoved:connect(function(x,y) local barAbsPos = scrollbar.AbsolutePosition.y local barAbsSize = scrollbar.AbsoluteSize.y local dragAbsSize = scrollDrag.AbsoluteSize.y local barAbsOne = barAbsPos + barAbsSize - dragAbsSize y = y - mouseOffset y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y y = y - barAbsPos local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end local doublePercent = y/(barAbsSize-dragAbsSize) local rowDiff = rowSize local totalScrollCount = guiObjects - (howManyDisplayed - 1) local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff if newScrollPosition < scrollPosition then rowDiff = -rowDiff end if newScrollPosition < 1 then newScrollPosition = 1 end scrollPosition = newScrollPosition recalculate(nil) end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect( function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect( function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollbar.MouseButton1Down:connect( function(x,y) if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then scrollDown(y) elseif y < (scrollDrag.AbsolutePosition.y) then scrollUp(y) end end) frame.ChildAdded:connect(function() recalculate(nil) end) frame.ChildRemoved:connect(function() recalculate(nil) end) frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(function() recalculate(nil) end) return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar end local function binaryGrow(min, max, fits) if min > max then return min end local biggestLegal = min while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then biggestLegal = mid --Try growing min = mid + 1 else --Doesn't fit, shrink max = mid - 1 end end return biggestLegal end local function binaryShrink(min, max, fits) if min > max then return min end local smallestLegal = max while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then smallestLegal = mid --It fits, shrink max = mid - 1 else --Doesn't fit, grow min = mid + 1 end end return smallestLegal end local function getGuiOwner(instance) while instance ~= nil do if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then return instance end instance = instance.Parent end return nil end t.AutoTruncateTextObject = function(textLabel) local text = textLabel.Text local fullLabel = textLabel:Clone() fullLabel.Name = "Full" .. textLabel.Name fullLabel.BorderSizePixel = 0 fullLabel.BackgroundTransparency = 0 fullLabel.Text = text fullLabel.TextXAlignment = Enum.TextXAlignment.Center fullLabel.Position = UDim2.new(0,-3,0,0) fullLabel.Size = UDim2.new(0,100,1,0) fullLabel.Visible = false fullLabel.Parent = textLabel local shortText = nil local mouseEnterConnection = nil local mouseLeaveConnection= nil local checkForResize = function() if getGuiOwner(textLabel) == nil then return end textLabel.Text = text if textLabel.TextFits then --Tear down the rollover if it is active if mouseEnterConnection then mouseEnterConnection:disconnect() mouseEnterConnection = nil end if mouseLeaveConnection then mouseLeaveConnection:disconnect() mouseLeaveConnection = nil end else local len = string.len(text) textLabel.Text = text .. "~" --Shrink the text local textSize = binaryGrow(0, len, function(pos) if pos == 0 then textLabel.Text = "~" else textLabel.Text = string.sub(text, 1, pos) .. "~" end return textLabel.TextFits end) shortText = string.sub(text, 1, textSize) .. "~" textLabel.Text = shortText --Make sure the fullLabel fits if not fullLabel.TextFits then --Already too small, grow it really bit to start fullLabel.Size = UDim2.new(0, 10000, 1, 0) end --Okay, now try to binary shrink it back down local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X, function(size) fullLabel.Size = UDim2.new(0, size, 1, 0) return fullLabel.TextFits end) fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0) --Now setup the rollover effects, if they are currently off if mouseEnterConnection == nil then mouseEnterConnection = textLabel.MouseEnter:connect( function() fullLabel.ZIndex = textLabel.ZIndex + 1 fullLabel.Visible = true --textLabel.Text = "" end) end if mouseLeaveConnection == nil then mouseLeaveConnection = textLabel.MouseLeave:connect( function() fullLabel.Visible = false --textLabel.Text = shortText end) end end end textLabel.AncestryChanged:connect(checkForResize) textLabel.Changed:connect( function(prop) if prop == "AbsoluteSize" then checkForResize() end end) checkForResize() local function changeText(newText) text = newText fullLabel.Text = text checkForResize() end return textLabel, changeText end local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue) if fromPage then fromPage.Visible = false if transitionFrame.Visible == false then transitionFrame.Size = fromPage.Size transitionFrame.Position = fromPage.Position end else if transitionFrame.Visible == false then transitionFrame.Size = UDim2.new(0.0,50,0.0,50) transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25) end end transitionFrame.Visible = true currentPageValue.Value = nil local newsize, newPosition if toPage then --Make it visible so it resizes toPage.Visible = true newSize = toPage.Size newPosition = toPage.Position toPage.Visible = false else newSize = UDim2.new(0.0,50,0.0,50) newPosition = UDim2.new(0.5,-25,0.5,-25) end transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true, function(state) if state == Enum.TweenStatus.Completed then transitionFrame.Visible = false if toPage then toPage.Visible = true currentPageValue.Value = toPage end end end) end t.CreateTutorial = function(name, tutorialKey, createButtons) local frame = Instance.new("Frame") frame.Name = "Tutorial-" .. name frame.BackgroundTransparency = 1 frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) local transitionFrame = Instance.new("Frame") transitionFrame.Name = "TransitionFrame" transitionFrame.Style = Enum.FrameStyle.RobloxRound transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0) transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0) transitionFrame.Visible = false transitionFrame.Parent = frame local currentPageValue = Instance.new("ObjectValue") currentPageValue.Name = "CurrentTutorialPage" currentPageValue.Value = nil currentPageValue.Parent = frame local boolValue = Instance.new("BoolValue") boolValue.Name = "Buttons" boolValue.Value = createButtons boolValue.Parent = frame local pages = Instance.new("Frame") pages.Name = "Pages" pages.BackgroundTransparency = 1 pages.Size = UDim2.new(1,0,1,0) pages.Parent = frame local function getVisiblePageAndHideOthers() local visiblePage = nil local children = pages:GetChildren() if children then for i,child in ipairs(children) do if child.Visible then if visiblePage then child.Visible = false else visiblePage = child end end end end return visiblePage end local showTutorial = function(alwaysShow) if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then print("Showing tutorial-",tutorialKey) local currentTutorialPage = getVisiblePageAndHideOthers() local firstPage = pages:FindFirstChild("TutorialPage1") if firstPage then TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue) else error("Could not find TutorialPage1") end end end local dismissTutorial = function() local currentTutorialPage = getVisiblePageAndHideOthers() if currentTutorialPage then TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue) end UserSettings().GameSettings:SetTutorialState(tutorialKey, true) end local gotoPage = function(pageNum) local page = pages:FindFirstChild("TutorialPage" .. pageNum) local currentTutorialPage = getVisiblePageAndHideOthers() TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue) end return frame, showTutorial, dismissTutorial, gotoPage end local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton) local frame = Instance.new("Frame") frame.Name = "TutorialPage" frame.Style = Enum.FrameStyle.RobloxRound frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) frame.Visible = false local frameHeader = Instance.new("TextLabel") frameHeader.Name = "Header" frameHeader.Text = name frameHeader.BackgroundTransparency = 1 frameHeader.FontSize = Enum.FontSize.Size24 frameHeader.Font = Enum.Font.ArialBold frameHeader.TextColor3 = Color3.new(1,1,1) frameHeader.TextXAlignment = Enum.TextXAlignment.Center frameHeader.TextWrap = true frameHeader.Size = UDim2.new(1,-55, 0, 22) frameHeader.Position = UDim2.new(0,0,0,0) frameHeader.Parent = frame local skipButton = Instance.new("ImageButton") skipButton.Name = "SkipButton" skipButton.AutoButtonColor = false skipButton.BackgroundTransparency = 1 skipButton.Image = "rbxasset://textures/ui/closeButton.png" skipButton.MouseButton1Click:connect(function() skipTutorial() end) skipButton.MouseEnter:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png" end) skipButton.MouseLeave:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton.png" end) skipButton.Size = UDim2.new(0, 25, 0, 25) skipButton.Position = UDim2.new(1, -25, 0, 0) skipButton.Parent = frame if giveDoneButton then local doneButton = Instance.new("TextButton") doneButton.Name = "DoneButton" doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault doneButton.Text = "Done" doneButton.TextColor3 = Color3.new(1,1,1) doneButton.Font = Enum.Font.ArialBold doneButton.FontSize = Enum.FontSize.Size18 doneButton.Size = UDim2.new(0,100,0,50) doneButton.Position = UDim2.new(0.5,-50,1,-50) if skipTutorial then doneButton.MouseButton1Click:connect(function() skipTutorial() end) end doneButton.Parent = frame end local innerFrame = Instance.new("Frame") innerFrame.Name = "ContentFrame" innerFrame.BackgroundTransparency = 1 innerFrame.Position = UDim2.new(0,0,0,25) innerFrame.Parent = frame local nextButton = Instance.new("TextButton") nextButton.Name = "NextButton" nextButton.Text = "Next" nextButton.TextColor3 = Color3.new(1,1,1) nextButton.Font = Enum.Font.Arial nextButton.FontSize = Enum.FontSize.Size18 nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault nextButton.Size = UDim2.new(0,80, 0, 32) nextButton.Position = UDim2.new(0.5, 5, 1, -32) nextButton.Active = false nextButton.Visible = false nextButton.Parent = frame local prevButton = Instance.new("TextButton") prevButton.Name = "PrevButton" prevButton.Text = "Previous" prevButton.TextColor3 = Color3.new(1,1,1) prevButton.Font = Enum.Font.Arial prevButton.FontSize = Enum.FontSize.Size18 prevButton.Style = Enum.ButtonStyle.RobloxButton prevButton.Size = UDim2.new(0,80, 0, 32) prevButton.Position = UDim2.new(0.5, -85, 1, -32) prevButton.Active = false prevButton.Visible = false prevButton.Parent = frame if giveDoneButton then innerFrame.Size = UDim2.new(1,0,1,-75) else innerFrame.Size = UDim2.new(1,0,1,-22) end local parentConnection = nil local function basicHandleResize() if frame.Visible and frame.Parent then local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y) handleResize(200,maxSize) end end frame.Changed:connect( function(prop) if prop == "Parent" then if parentConnection ~= nil then parentConnection:disconnect() parentConnection = nil end if frame.Parent and frame.Parent:IsA("GuiObject") then parentConnection = frame.Parent.Changed:connect( function(parentProp) if parentProp == "AbsoluteSize" then wait() basicHandleResize() end end) basicHandleResize() end end if prop == "Visible" then basicHandleResize() end end) return frame, innerFrame end t.CreateTextTutorialPage = function(name, text, skipTutorialFunc) local frame = nil local contentFrame = nil local textLabel = Instance.new("TextLabel") textLabel.BackgroundTransparency = 1 textLabel.TextColor3 = Color3.new(1,1,1) textLabel.Text = text textLabel.TextWrap = true textLabel.TextXAlignment = Enum.TextXAlignment.Left textLabel.TextYAlignment = Enum.TextYAlignment.Center textLabel.Font = Enum.Font.Arial textLabel.FontSize = Enum.FontSize.Size14 textLabel.Size = UDim2.new(1,0,1,0) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) frame.Size = UDim2.new(0, size, 0, size) return textLabel.TextFits end) frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc) textLabel.Parent = contentFrame return frame end t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton) local frame = nil local contentFrame = nil local imageLabel = Instance.new("ImageLabel") imageLabel.BackgroundTransparency = 1 imageLabel.Image = imageAsset imageLabel.Size = UDim2.new(0,x,0,y) imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) return size >= x and size >= y end) if size >= x and size >= y then imageLabel.Size = UDim2.new(0,x, 0,y) imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2) else if x > y then --X is limiter, so imageLabel.Size = UDim2.new(1,0,y/x,0) imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0) else --Y is limiter imageLabel.Size = UDim2.new(x/y,0,1, 0) imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0) end end size = size + 50 frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton) imageLabel.Parent = contentFrame return frame end t.AddTutorialPage = function(tutorial, tutorialPage) local transitionFrame = tutorial.TransitionFrame local currentPageValue = tutorial.CurrentTutorialPage if not tutorial.Buttons.Value then tutorialPage.NextButton.Parent = nil tutorialPage.PrevButton.Parent = nil end local children = tutorial.Pages:GetChildren() if children and #children > 0 then tutorialPage.Name = "TutorialPage" .. (#children+1) local previousPage = children[#children] if not previousPage:IsA("GuiObject") then error("All elements under Pages must be GuiObjects") end if tutorial.Buttons.Value then if previousPage.NextButton.Active then error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function") end previousPage.NextButton.MouseButton1Click:connect( function() TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue) end) previousPage.NextButton.Active = true previousPage.NextButton.Visible = true if tutorialPage.PrevButton.Active then error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function") end tutorialPage.PrevButton.MouseButton1Click:connect( function() TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue) end) tutorialPage.PrevButton.Active = true tutorialPage.PrevButton.Visible = true end tutorialPage.Parent = tutorial.Pages else --First child tutorialPage.Name = "TutorialPage1" tutorialPage.Parent = tutorial.Pages end end t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId) if not userIdsForSets then error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids") end if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata") end if not objectSelected then error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!") end if type(objectSelected) ~= "function" then error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!") end if dialogClosed and type(dialogClosed) ~= "function" then error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!") end if showAdminCategories == nil then -- by default, don't show beta sets showAdminCategories = false end local arrayPosition = 1 local insertButtons = {} local insertButtonCons = {} local contents = nil local setGui = nil -- used for water selections local waterForceDirection = "NegX" local waterForce = "None" local waterGui, waterTypeChangedEvent = nil local Data = {} Data.CurrentCategory = nil Data.Category = {} local SetCache = {} local userCategoryButtons = nil local buttonWidth = 64 local buttonHeight = buttonWidth local SmallThumbnailUrl = nil local LargeThumbnailUrl = nil local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower() if useAssetVersionId then LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid=" else LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid=" end local function drillDownSetZIndex(parent, index) local children = parent:GetChildren() for i = 1, #children do if children[i]:IsA("GuiObject") then children[i].ZIndex = index end drillDownSetZIndex(children[i], index) end end -- for terrain stamping local currTerrainDropDownFrame = nil local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"} local terrainShapeMap = {} for i = 1, #terrainShapes do terrainShapeMap[terrainShapes[i]] = i - 1 end terrainShapeMap[terrainShapes[#terrainShapes]] = 6 local function createWaterGui() local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"} local waterForces = {"None", "Small", "Medium", "Strong", "Max"} local waterFrame = Instance.new("Frame") waterFrame.Name = "WaterFrame" waterFrame.Style = Enum.FrameStyle.RobloxSquare waterFrame.Size = UDim2.new(0,150,0,110) waterFrame.Visible = false local waterForceLabel = Instance.new("TextLabel") waterForceLabel.Name = "WaterForceLabel" waterForceLabel.BackgroundTransparency = 1 waterForceLabel.Size = UDim2.new(1,0,0,12) waterForceLabel.Font = Enum.Font.ArialBold waterForceLabel.FontSize = Enum.FontSize.Size12 waterForceLabel.TextColor3 = Color3.new(1,1,1) waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left waterForceLabel.Text = "Water Force" waterForceLabel.Parent = waterFrame local waterForceDirLabel = waterForceLabel:Clone() waterForceDirLabel.Name = "WaterForceDirectionLabel" waterForceDirLabel.Text = "Water Force Direction" waterForceDirLabel.Position = UDim2.new(0,0,0,50) waterForceDirLabel.Parent = waterFrame local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame) waterTypeChangedEvent.Name = "WaterTypeChangedEvent" local waterForceDirectionSelectedFunc = function(newForceDirection) waterForceDirection = newForceDirection waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceSelectedFunc = function(newForce) waterForce = newForce waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc) waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25) waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3) forceWaterDirectionSelection("NegX") waterForceDirectionDropDown.Parent = waterForceDirLabel local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc) forceWaterForceSelection("None") waterForceDropDown.Size = UDim2.new(1,0,0,25) waterForceDropDown.Position = UDim2.new(0,0,1,3) waterForceDropDown.Parent = waterForceLabel return waterFrame, waterTypeChangedEvent end -- Helper Function that contructs gui elements local function createSetGui() local setGui = Instance.new("ScreenGui") setGui.Name = "SetGui" local setPanel = Instance.new("Frame") setPanel.Name = "SetPanel" setPanel.Active = true setPanel.BackgroundTransparency = 1 if position then setPanel.Position = position else setPanel.Position = UDim2.new(0.2, 29, 0.1, 24) end if size then setPanel.Size = size else setPanel.Size = UDim2.new(0.6, -58, 0.64, 0) end setPanel.Style = Enum.FrameStyle.RobloxRound setPanel.ZIndex = 6 setPanel.Parent = setGui -- Children of SetPanel local itemPreview = Instance.new("Frame") itemPreview.Name = "ItemPreview" itemPreview.BackgroundTransparency = 1 itemPreview.Position = UDim2.new(0.8,5,0.085,0) itemPreview.Size = UDim2.new(0.21,0,0.9,0) itemPreview.ZIndex = 6 itemPreview.Parent = setPanel -- Children of ItemPreview local textPanel = Instance.new("Frame") textPanel.Name = "TextPanel" textPanel.BackgroundTransparency = 1 textPanel.Position = UDim2.new(0,0,0.45,0) textPanel.Size = UDim2.new(1,0,0.55,0) textPanel.ZIndex = 6 textPanel.Parent = itemPreview -- Children of TextPanel local rolloverText = Instance.new("TextLabel") rolloverText.Name = "RolloverText" rolloverText.BackgroundTransparency = 1 rolloverText.Size = UDim2.new(1,0,0,48) rolloverText.ZIndex = 6 rolloverText.Font = Enum.Font.ArialBold rolloverText.FontSize = Enum.FontSize.Size24 rolloverText.Text = "" rolloverText.TextColor3 = Color3.new(1,1,1) rolloverText.TextWrap = true rolloverText.TextXAlignment = Enum.TextXAlignment.Left rolloverText.TextYAlignment = Enum.TextYAlignment.Top rolloverText.Parent = textPanel local largePreview = Instance.new("ImageLabel") largePreview.Name = "LargePreview" largePreview.BackgroundTransparency = 1 largePreview.Image = "" largePreview.Size = UDim2.new(1,0,0,170) largePreview.ZIndex = 6 largePreview.Parent = itemPreview local sets = Instance.new("Frame") sets.Name = "Sets" sets.BackgroundTransparency = 1 sets.Position = UDim2.new(0,0,0,5) sets.Size = UDim2.new(0.23,0,1,-5) sets.ZIndex = 6 sets.Parent = setPanel -- Children of Sets local line = Instance.new("Frame") line.Name = "Line" line.BackgroundColor3 = Color3.new(1,1,1) line.BackgroundTransparency = 0.7 line.BorderSizePixel = 0 line.Position = UDim2.new(1,-3,0.06,0) line.Size = UDim2.new(0,3,0.9,0) line.ZIndex = 6 line.Parent = sets local setsLists, controlFrame = t.CreateTrueScrollingFrame() setsLists.Size = UDim2.new(1,-6,0.94,0) setsLists.Position = UDim2.new(0,0,0.06,0) setsLists.BackgroundTransparency = 1 setsLists.Name = "SetsLists" setsLists.ZIndex = 6 setsLists.Parent = sets drillDownSetZIndex(controlFrame, 7) local setsHeader = Instance.new("TextLabel") setsHeader.Name = "SetsHeader" setsHeader.BackgroundTransparency = 1 setsHeader.Size = UDim2.new(0,47,0,24) setsHeader.ZIndex = 6 setsHeader.Font = Enum.Font.ArialBold setsHeader.FontSize = Enum.FontSize.Size24 setsHeader.Text = "Sets" setsHeader.TextColor3 = Color3.new(1,1,1) setsHeader.TextXAlignment = Enum.TextXAlignment.Left setsHeader.TextYAlignment = Enum.TextYAlignment.Top setsHeader.Parent = sets local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(1,-32,0,-2) cancelButton.Size = UDim2.new(0,34,0,34) cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault cancelButton.ZIndex = 6 cancelButton.Text = "" cancelButton.Modal = true cancelButton.Parent = setPanel -- Children of Cancel Button local cancelImage = Instance.new("ImageLabel") cancelImage.Name = "CancelImage" cancelImage.BackgroundTransparency = 1 cancelImage.Image = "http://www.roblox.com/asset/?id=54135717" cancelImage.Position = UDim2.new(0,-2,0,-2) cancelImage.Size = UDim2.new(0,16,0,16) cancelImage.ZIndex = 6 cancelImage.Parent = cancelButton return setGui end local function createSetButton(text) local setButton = Instance.new("TextButton") if text then setButton.Text = text else setButton.Text = "" end setButton.AutoButtonColor = false setButton.BackgroundTransparency = 1 setButton.BackgroundColor3 = Color3.new(1,1,1) setButton.BorderSizePixel = 0 setButton.Size = UDim2.new(1,-5,0,18) setButton.ZIndex = 6 setButton.Visible = false setButton.Font = Enum.Font.Arial setButton.FontSize = Enum.FontSize.Size18 setButton.TextColor3 = Color3.new(1,1,1) setButton.TextXAlignment = Enum.TextXAlignment.Left return setButton end local function buildSetButton(name, setId, setImageId, i, count) local button = createSetButton(name) button.Text = name button.Name = "SetButton" button.Visible = true local setValue = Instance.new("IntValue") setValue.Name = "SetId" setValue.Value = setId setValue.Parent = button local setName = Instance.new("StringValue") setName.Name = "SetName" setName.Value = name setName.Parent = button return button end local function processCategory(sets) local setButtons = {} local numSkipped = 0 for i = 1, #sets do if not showAdminCategories and sets[i].Name == "Beta" then numSkipped = numSkipped + 1 else setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets) end end return setButtons end local function handleResize() wait() -- neccessary to insure heartbeat happened local itemPreview = setGui.SetPanel.ItemPreview itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X) itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0) itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y) itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y) end local function makeInsertAssetButton() local insertAssetButtonExample = Instance.new("Frame") insertAssetButtonExample.Name = "InsertAssetButtonExample" insertAssetButtonExample.Position = UDim2.new(0,128,0,64) insertAssetButtonExample.Size = UDim2.new(0,64,0,64) insertAssetButtonExample.BackgroundTransparency = 1 insertAssetButtonExample.ZIndex = 6 insertAssetButtonExample.Visible = false local assetId = Instance.new("IntValue") assetId.Name = "AssetId" assetId.Value = 0 assetId.Parent = insertAssetButtonExample local assetName = Instance.new("StringValue") assetName.Name = "AssetName" assetName.Value = "" assetName.Parent = insertAssetButtonExample local button = Instance.new("TextButton") button.Name = "Button" button.Text = "" button.Style = Enum.ButtonStyle.RobloxButton button.Position = UDim2.new(0.025,0,0.025,0) button.Size = UDim2.new(0.95,0,0.95,0) button.ZIndex = 6 button.Parent = insertAssetButtonExample local buttonImage = Instance.new("ImageLabel") buttonImage.Name = "ButtonImage" buttonImage.Image = "" buttonImage.Position = UDim2.new(0,-7,0,-7) buttonImage.Size = UDim2.new(1,14,1,14) buttonImage.BackgroundTransparency = 1 buttonImage.ZIndex = 7 buttonImage.Parent = button local configIcon = buttonImage:clone() configIcon.Name = "ConfigIcon" configIcon.Visible = false configIcon.Position = UDim2.new(1,-23,1,-24) configIcon.Size = UDim2.new(0,16,0,16) configIcon.Image = "" configIcon.ZIndex = 6 configIcon.Parent = insertAssetButtonExample return insertAssetButtonExample end local function showLargePreview(insertButton) if insertButton:FindFirstChild("AssetId") then delay(0,function() game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)) setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value) end) end if insertButton:FindFirstChild("AssetName") then setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value end end local function selectTerrainShape(shape) if currTerrainDropDownFrame then objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape) end end local function createTerrainTypeButton(name, parent) local dropDownTextButton = Instance.new("TextButton") dropDownTextButton.Name = name .. "Button" dropDownTextButton.Font = Enum.Font.ArialBold dropDownTextButton.FontSize = Enum.FontSize.Size14 dropDownTextButton.BorderSizePixel = 0 dropDownTextButton.TextColor3 = Color3.new(1,1,1) dropDownTextButton.Text = name dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.ZIndex = parent.ZIndex + 1 dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16) dropDownTextButton.Position = UDim2.new(0,1,0,0) dropDownTextButton.MouseEnter:connect(function() dropDownTextButton.BackgroundTransparency = 0 dropDownTextButton.TextColor3 = Color3.new(0,0,0) end) dropDownTextButton.MouseLeave:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) end) dropDownTextButton.MouseButton1Click:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then dropDownTextButton.Parent.Visible = false end selectTerrainShape(terrainShapeMap[dropDownTextButton.Text]) end) return dropDownTextButton end local function createTerrainDropDownMenu(zIndex) local dropDown = Instance.new("Frame") dropDown.Name = "TerrainDropDown" dropDown.BackgroundColor3 = Color3.new(0,0,0) dropDown.BorderColor3 = Color3.new(1,0,0) dropDown.Size = UDim2.new(0,200,0,0) dropDown.Visible = false dropDown.ZIndex = zIndex dropDown.Parent = setGui for i = 1, #terrainShapes do local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown) shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset)) shapeButton.Parent = dropDown dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset)) end dropDown.MouseLeave:connect(function() dropDown.Visible = false end) end local function createDropDownMenuButton(parent) local dropDownButton = Instance.new("ImageButton") dropDownButton.Name = "DropDownButton" dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509" dropDownButton.BackgroundTransparency = 1 dropDownButton.Size = UDim2.new(0,16,0,16) dropDownButton.Position = UDim2.new(1,-24,0,6) dropDownButton.ZIndex = parent.ZIndex + 2 dropDownButton.Parent = parent if not setGui:FindFirstChild("TerrainDropDown") then createTerrainDropDownMenu(8) end dropDownButton.MouseButton1Click:connect(function() setGui.TerrainDropDown.Visible = true setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y) currTerrainDropDownFrame = parent end) end local function buildInsertButton() local insertButton = makeInsertAssetButton() insertButton.Name = "InsertAssetButton" insertButton.Visible = true if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then createDropDownMenuButton(insertButton) end local lastEnter = nil local mouseEnterCon = insertButton.MouseEnter:connect(function() lastEnter = insertButton delay(0.1,function() if lastEnter == insertButton then showLargePreview(insertButton) end end) end) return insertButton, mouseEnterCon end local function realignButtonGrid(columns) local x = 0 local y = 0 for i = 1, #insertButtons do insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y) x = x + 1 if x >= columns then x = 0 y = y + 1 end end end local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId) if visible then insertFrame.AssetName.Value = name insertFrame.AssetId.Value = assetId local newImageUrl = SmallThumbnailUrl .. assetId if newImageUrl ~= insertFrame.Button.ButtonImage.Image then delay(0,function() game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId) if insertFrame:findFirstChild("Button") then insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId end end) end table.insert(insertButtonCons, insertFrame.Button.MouseButton1Click:connect(function() -- special case for water, show water selection gui local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability") waterGui.Visible = isWaterSelected if isWaterSelected then objectSelected(name, tonumber(assetId), nil) else objectSelected(name, tonumber(assetId)) end end) ) insertFrame.Visible = true else insertFrame.Visible = false end end local function loadSectionOfItems(setGui, rows, columns) local pageSize = rows * columns if arrayPosition > #contents then return end local origArrayPos = arrayPosition local yCopy = 0 for i = 1, pageSize + 1 do if arrayPosition >= #contents + 1 then break end local buttonCon insertButtons[arrayPosition], buttonCon = buildInsertButton() table.insert(insertButtonCons,buttonCon) insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame arrayPosition = arrayPosition + 1 end realignButtonGrid(columns) local indexCopy = origArrayPos for index = origArrayPos, arrayPosition do if insertButtons[index] then if contents[index] then -- we don't want water to have a drop down button if contents[index].Name == "Water" then if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy() end end local assetId if useAssetVersionId then assetId = contents[index].AssetVersionId else assetId = contents[index].AssetId end setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId) else break end else break end indexCopy = index end end local function setSetIndex() Data.Category[Data.CurrentCategory].Index = 0 rows = 7 columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) contents = Data.Category[Data.CurrentCategory].Contents if contents then -- remove our buttons and their connections for i = 1, #insertButtons do insertButtons[i]:remove() end for i = 1, #insertButtonCons do if insertButtonCons[i] then insertButtonCons[i]:disconnect() end end insertButtonCons = {} insertButtons = {} arrayPosition = 1 loadSectionOfItems(setGui, rows, columns) end end local function selectSet(button, setName, setId, setIndex) if button and Data.Category[Data.CurrentCategory] ~= nil then if button ~= Data.Category[Data.CurrentCategory].Button then Data.Category[Data.CurrentCategory].Button = button if SetCache[setId] == nil then SetCache[setId] = game:GetService("InsertService"):GetCollection(setId) end Data.Category[Data.CurrentCategory].Contents = SetCache[setId] Data.Category[Data.CurrentCategory].SetName = setName Data.Category[Data.CurrentCategory].SetId = setId end setSetIndex() end end local function selectCategoryPage(buttons, page) if buttons ~= Data.CurrentCategory then if Data.CurrentCategory then for key, button in pairs(Data.CurrentCategory) do button.Visible = false end end Data.CurrentCategory = buttons if Data.Category[Data.CurrentCategory] == nil then Data.Category[Data.CurrentCategory] = {} if #buttons > 0 then selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0) end else Data.Category[Data.CurrentCategory].Button = nil selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index) end end end local function selectCategory(category) selectCategoryPage(category, 0) end local function resetAllSetButtonSelection() local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren() for i = 1, #setButtons do if setButtons[i]:IsA("TextButton") then setButtons[i].Selected = false setButtons[i].BackgroundTransparency = 1 setButtons[i].TextColor3 = Color3.new(1,1,1) setButtons[i].BackgroundColor3 = Color3.new(1,1,1) end end end local function populateSetsFrame() local currRow = 0 for i = 1, #userCategoryButtons do local button = userCategoryButtons[i] button.Visible = true button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset) button.Parent = setGui.SetPanel.Sets.SetsLists if i == 1 then -- we will have this selected by default, so show it button.Selected = true button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 end button.MouseEnter:connect(function() if not button.Selected then button.BackgroundTransparency = 0 button.TextColor3 = Color3.new(0,0,0) end end) button.MouseLeave:connect(function() if not button.Selected then button.BackgroundTransparency = 1 button.TextColor3 = Color3.new(1,1,1) end end) button.MouseButton1Click:connect(function() resetAllSetButtonSelection() button.Selected = not button.Selected button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0) end) currRow = currRow + 1 end local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren() -- set first category as loaded for default if buttons then for i = 1, #buttons do if buttons[i]:IsA("TextButton") then selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0) selectCategory(userCategoryButtons) break end end end end setGui = createSetGui() waterGui, waterTypeChangedEvent = createWaterGui() waterGui.Position = UDim2.new(0,55,0,0) waterGui.Parent = setGui setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size if prop == "AbsoluteSize" then handleResize() setSetIndex() end end) local scrollFrame, controlFrame = t.CreateTrueScrollingFrame() scrollFrame.Size = UDim2.new(0.54,0,0.85,0) scrollFrame.Position = UDim2.new(0.24,0,0.085,0) scrollFrame.Name = "ItemsFrame" scrollFrame.ZIndex = 6 scrollFrame.Parent = setGui.SetPanel scrollFrame.BackgroundTransparency = 1 drillDownSetZIndex(controlFrame,7) controlFrame.Parent = setGui.SetPanel controlFrame.Position = UDim2.new(0.76, 5, 0, 0) local debounce = false controlFrame.ScrollBottom.Changed:connect(function(prop) if controlFrame.ScrollBottom.Value == true then if debounce then return end debounce = true loadSectionOfItems(setGui, rows, columns) debounce = false end end) local userData = {} for id = 1, #userIdsForSets do local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id]) if newUserData and #newUserData > 2 then -- start at #3 to skip over My Decals and My Models for each account for category = 3, #newUserData do if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first table.insert(userData,1,newUserData[category]) else table.insert(userData, newUserData[category]) end end end end if userData then userCategoryButtons = processCategory(userData) end rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight) columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) populateSetsFrame() insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function() setGui.SetPanel.Visible = false if dialogClosed then dialogClosed() end end) local setVisibilityFunction = function(visible) if visible then setGui.SetPanel.Visible = true else setGui.SetPanel.Visible = false end end local getVisibilityFunction = function() if setGui then if setGui:FindFirstChild("SetPanel") then return setGui.SetPanel.Visible end end return false end return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent end t.CreateTerrainMaterialSelector = function(size,position) local terrainMaterialSelectionChanged = Instance.new("BindableEvent") terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged" local selectedButton = nil local frame = Instance.new("Frame") frame.Name = "TerrainMaterialSelector" if size then frame.Size = size else frame.Size = UDim2.new(0, 245, 0, 230) end if position then frame.Position = position end frame.BorderSizePixel = 0 frame.BackgroundColor3 = Color3.new(0,0,0) frame.Active = true terrainMaterialSelectionChanged.Parent = frame local waterEnabled = true -- todo: turn this on when water is ready local materialToImageMap = {} local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"} if waterEnabled then table.insert(materialNames,"Water") end local currentMaterial = 1 function getEnumFromName(choice) if choice == "Grass" then return 1 end if choice == "Sand" then return 2 end if choice == "Erase" then return 0 end if choice == "Brick" then return 3 end if choice == "Granite" then return 4 end if choice == "Asphalt" then return 5 end if choice == "Iron" then return 6 end if choice == "Aluminum" then return 7 end if choice == "Gold" then return 8 end if choice == "Plank" then return 9 end if choice == "Log" then return 10 end if choice == "Gravel" then return 11 end if choice == "Cinder Block" then return 12 end if choice == "Stone Wall" then return 13 end if choice == "Concrete" then return 14 end if choice == "Plastic (red)" then return 15 end if choice == "Plastic (blue)" then return 16 end if choice == "Water" then return 17 end end function getNameFromEnum(choice) if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end if waterEnabled then if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end end end local function updateMaterialChoice(choice) currentMaterial = getEnumFromName(choice) terrainMaterialSelectionChanged:Fire(currentMaterial) end -- we so need a better way to do this for i,v in pairs(materialNames) do materialToImageMap[v] = {} if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112" elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652" elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537" elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153" elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038" elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093" elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995" elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118" elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848" elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924" elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015" elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051" elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206" elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103" elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804" elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059" elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474" else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!! end end local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid") scrollFrame.Size = UDim2.new(0.85,0,1,0) scrollFrame.Position = UDim2.new(0,0,0,0) scrollFrame.Parent = frame scrollUp.Parent = frame scrollUp.Visible = true scrollUp.Position = UDim2.new(1,-19,0,0) scrollDown.Parent = frame scrollDown.Visible = true scrollDown.Position = UDim2.new(1,-19,1,-17) local function goToNewMaterial(buttonWrap, materialName) updateMaterialChoice(materialName) buttonWrap.BackgroundTransparency = 0 selectedButton.BackgroundTransparency = 1 selectedButton = buttonWrap end local function createMaterialButton(name) local buttonWrap = Instance.new("TextButton") buttonWrap.Text = "" buttonWrap.Size = UDim2.new(0,32,0,32) buttonWrap.BackgroundColor3 = Color3.new(1,1,1) buttonWrap.BorderSizePixel = 0 buttonWrap.BackgroundTransparency = 1 buttonWrap.AutoButtonColor = false buttonWrap.Name = tostring(name) local imageButton = Instance.new("ImageButton") imageButton.AutoButtonColor = false imageButton.BackgroundTransparency = 1 imageButton.Size = UDim2.new(0,30,0,30) imageButton.Position = UDim2.new(0,1,0,1) imageButton.Name = tostring(name) imageButton.Parent = buttonWrap imageButton.Image = materialToImageMap[name].Regular local enumType = Instance.new("NumberValue") enumType.Name = "EnumType" enumType.Parent = buttonWrap enumType.Value = 0 imageButton.MouseEnter:connect(function() buttonWrap.BackgroundTransparency = 0 end) imageButton.MouseLeave:connect(function() if selectedButton ~= buttonWrap then buttonWrap.BackgroundTransparency = 1 end end) imageButton.MouseButton1Click:connect(function() if selectedButton ~= buttonWrap then goToNewMaterial(buttonWrap, tostring(name)) end end) return buttonWrap end for i = 1, #materialNames do local imageButton = createMaterialButton(materialNames[i]) if materialNames[i] == "Grass" then -- always start with grass as the default selectedButton = imageButton imageButton.BackgroundTransparency = 0 end imageButton.Parent = scrollFrame end local forceTerrainMaterialSelection = function(newMaterialType) if not newMaterialType then return end if currentMaterial == newMaterialType then return end local matName = getNameFromEnum(newMaterialType) local buttons = scrollFrame:GetChildren() for i = 1, #buttons do if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end if string.find(buttons[i].Name, matName) then goToNewMaterial(buttons[i],matName) return end end end frame.Changed:connect(function ( prop ) if prop == "AbsoluteSize" then recalculateScroll() end end) recalculateScroll() return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection end t.CreateLoadingFrame = function(name,size,position) game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053") local loadingFrame = Instance.new("Frame") loadingFrame.Name = "LoadingFrame" loadingFrame.Style = Enum.FrameStyle.RobloxRound if size then loadingFrame.Size = size else loadingFrame.Size = UDim2.new(0,300,0,160) end if position then loadingFrame.Position = position else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end local loadingBar = Instance.new("Frame") loadingBar.Name = "LoadingBar" loadingBar.BackgroundColor3 = Color3.new(0,0,0) loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255) loadingBar.Position = UDim2.new(0,0,0,41) loadingBar.Size = UDim2.new(1,0,0,30) loadingBar.Parent = loadingFrame local loadingGreenBar = Instance.new("ImageLabel") loadingGreenBar.Name = "LoadingGreenBar" loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053" loadingGreenBar.Position = UDim2.new(0,0,0,0) loadingGreenBar.Size = UDim2.new(0,0,1,0) loadingGreenBar.Visible = false loadingGreenBar.Parent = loadingBar local loadingPercent = Instance.new("TextLabel") loadingPercent.Name = "LoadingPercent" loadingPercent.BackgroundTransparency = 1 loadingPercent.Position = UDim2.new(0,0,1,0) loadingPercent.Size = UDim2.new(1,0,0,14) loadingPercent.Font = Enum.Font.Arial loadingPercent.Text = "0%" loadingPercent.FontSize = Enum.FontSize.Size14 loadingPercent.TextColor3 = Color3.new(1,1,1) loadingPercent.Parent = loadingBar local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(0.5,-60,1,-40) cancelButton.Size = UDim2.new(0,120,0,40) cancelButton.Font = Enum.Font.Arial cancelButton.FontSize = Enum.FontSize.Size18 cancelButton.TextColor3 = Color3.new(1,1,1) cancelButton.Text = "Cancel" cancelButton.Style = Enum.ButtonStyle.RobloxButton cancelButton.Parent = loadingFrame local loadingName = Instance.new("TextLabel") loadingName.Name = "loadingName" loadingName.BackgroundTransparency = 1 loadingName.Size = UDim2.new(1,0,0,18) loadingName.Position = UDim2.new(0,0,0,2) loadingName.Font = Enum.Font.Arial loadingName.Text = name loadingName.TextColor3 = Color3.new(1,1,1) loadingName.TextStrokeTransparency = 1 loadingName.FontSize = Enum.FontSize.Size18 loadingName.Parent = loadingFrame local cancelButtonClicked = Instance.new("BindableEvent") cancelButtonClicked.Name = "CancelButtonClicked" cancelButtonClicked.Parent = cancelButton cancelButton.MouseButton1Click:connect(function() cancelButtonClicked:Fire() end) local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength) if percent and type(percent) ~= "number" then error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead") end local newSize = nil if percent < 0 then newSize = UDim2.new(0,0,1,0) elseif percent > 1 then newSize = UDim2.new(1,0,1,0) else newSize = UDim2.new(percent,0,1,0) end if tweenAction then if not tweenLength then error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument") end if (newSize.X.Scale > 0) then loadingGreenBar.Visible = true loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true) else loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true, function() if (newSize.X.Scale < 0) then loadingGreenBar.Visible = false end end) end else loadingGreenBar.Size = newSize loadingGreenBar.Visible = (newSize.X.Scale > 0) end end loadingGreenBar.Changed:connect(function(prop) if prop == "Size" then loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%" end end) return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked end t.CreatePluginFrame = function (name,size,position,scrollable,parent) function createMenuButton(size,position,text,fontsize,name,parent) local button = Instance.new("TextButton",parent) button.AutoButtonColor = false button.Name = name button.BackgroundTransparency = 1 button.Position = position button.Size = size button.Font = Enum.Font.ArialBold button.FontSize = fontsize button.Text = text button.TextColor3 = Color3.new(1,1,1) button.BorderSizePixel = 0 button.BackgroundColor3 = Color3.new(20/255,20/255,20/255) button.MouseEnter:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 1 end) return button end local dragBar = Instance.new("Frame",parent) dragBar.Name = tostring(name) .. "DragBar" dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) dragBar.BorderColor3 = Color3.new(0,0,0) if size then dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0) else dragBar.Size = UDim2.new(0,183,0,20) end if position then dragBar.Position = position end dragBar.Active = true dragBar.Draggable = true --dragBar.Visible = false dragBar.MouseEnter:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255) end) dragBar.MouseLeave:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) end) -- plugin name label local pluginNameLabel = Instance.new("TextLabel",dragBar) pluginNameLabel.Name = "BarNameLabel" pluginNameLabel.Text = " " .. tostring(name) pluginNameLabel.TextColor3 = Color3.new(1,1,1) pluginNameLabel.TextStrokeTransparency = 0 pluginNameLabel.Size = UDim2.new(1,0,1,0) pluginNameLabel.Font = Enum.Font.ArialBold pluginNameLabel.FontSize = Enum.FontSize.Size18 pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left pluginNameLabel.BackgroundTransparency = 1 -- close button local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar) local closeEvent = Instance.new("BindableEvent") closeEvent.Name = "CloseEvent" closeEvent.Parent = closeButton closeButton.MouseButton1Click:connect(function () closeEvent:Fire() closeButton.BackgroundTransparency = 1 end) -- help button local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar) local helpFrame = Instance.new("Frame",dragBar) helpFrame.Name = "HelpFrame" helpFrame.BackgroundColor3 = Color3.new(0,0,0) helpFrame.Size = UDim2.new(0,300,0,552) helpFrame.Position = UDim2.new(1,5,0,0) helpFrame.Active = true helpFrame.BorderSizePixel = 0 helpFrame.Visible = false helpButton.MouseButton1Click:connect(function( ) helpFrame.Visible = not helpFrame.Visible if helpFrame.Visible then helpButton.Selected = true helpButton.BackgroundTransparency = 0 local screenGui = getScreenGuiAncestor(helpFrame) if screenGui then if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0) else -- position on right hand side helpFrame.Position = UDim2.new(1,5,0,0) end else helpFrame.Position = UDim2.new(1,5,0,0) end else helpButton.Selected = false helpButton.BackgroundTransparency = 1 end end) local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar) minimizeButton.TextYAlignment = Enum.TextYAlignment.Top local minimizeFrame = Instance.new("Frame",dragBar) minimizeFrame.Name = "MinimizeFrame" minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255) minimizeFrame.BorderColor3 = Color3.new(0,0,0) minimizeFrame.Position = UDim2.new(0,0,1,0) if size then minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0) else minimizeFrame.Size = UDim2.new(0,183,0,50) end minimizeFrame.Visible = false local minimizeBigButton = Instance.new("TextButton",minimizeFrame) minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20) minimizeBigButton.Name = "MinimizeButton" minimizeBigButton.Size = UDim2.new(0,100,0,40) minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton minimizeBigButton.Font = Enum.Font.ArialBold minimizeBigButton.FontSize = Enum.FontSize.Size18 minimizeBigButton.TextColor3 = Color3.new(1,1,1) minimizeBigButton.Text = "Show" local separatingLine = Instance.new("Frame",dragBar) separatingLine.Name = "SeparatingLine" separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255) separatingLine.BorderSizePixel = 0 separatingLine.Position = UDim2.new(1,-18,0.5,-7) separatingLine.Size = UDim2.new(0,1,0,14) local otherSeparatingLine = separatingLine:clone() otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7) otherSeparatingLine.Parent = dragBar local widgetContainer = Instance.new("Frame",dragBar) widgetContainer.Name = "WidgetContainer" widgetContainer.BackgroundTransparency = 1 widgetContainer.Position = UDim2.new(0,0,1,0) widgetContainer.BorderColor3 = Color3.new(0,0,0) if not scrollable then widgetContainer.BackgroundTransparency = 0 widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255) end if size then if scrollable then widgetContainer.Size = size else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset) end else if scrollable then widgetContainer.Size = UDim2.new(0,163,0,400) else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400) end end if position then widgetContainer.Position = position + UDim2.new(0,0,0,20) end local frame,control,verticalDragger = nil if scrollable then --frame for widgets frame,control = t.CreateTrueScrollingFrame() frame.Size = UDim2.new(1, 0, 1, 0) frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255) frame.BorderColor3 = Color3.new(0,0,0) frame.Active = true frame.Parent = widgetContainer control.Parent = dragBar control.BackgroundColor3 = Color3.new(72/255,72/255,72/255) control.BorderSizePixel = 0 control.BackgroundTransparency = 0 control.Position = UDim2.new(1,-21,1,1) if size then control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset) else control.Size = UDim2.new(0,21,0,400) end control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20) local fakeLine = Instance.new("Frame",control) fakeLine.Name = "FakeLine" fakeLine.BorderSizePixel = 0 fakeLine.BackgroundColor3 = Color3.new(0,0,0) fakeLine.Size = UDim2.new(0,1,1,1) fakeLine.Position = UDim2.new(1,0,0,0) verticalDragger = Instance.new("TextButton",widgetContainer) verticalDragger.ZIndex = 2 verticalDragger.AutoButtonColor = false verticalDragger.Name = "VerticalDragger" verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) verticalDragger.BorderColor3 = Color3.new(0,0,0) verticalDragger.Size = UDim2.new(1,20,0,20) verticalDragger.Position = UDim2.new(0,0,1,0) verticalDragger.Active = true verticalDragger.Text = "" local scrubFrame = Instance.new("Frame",verticalDragger) scrubFrame.Name = "ScrubFrame" scrubFrame.BackgroundColor3 = Color3.new(1,1,1) scrubFrame.BorderSizePixel = 0 scrubFrame.Position = UDim2.new(0.5,-5,0.5,0) scrubFrame.Size = UDim2.new(0,10,0,1) scrubFrame.ZIndex = 5 local scrubTwo = scrubFrame:clone() scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2) scrubTwo.Parent = verticalDragger local scrubThree = scrubFrame:clone() scrubThree.Position = UDim2.new(0.5,-5,0.5,2) scrubThree.Parent = verticalDragger local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent)) areaSoak.Name = "AreaSoak" areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.BackgroundTransparency = 1 areaSoak.BorderSizePixel = 0 areaSoak.Text = "" areaSoak.ZIndex = 10 areaSoak.Visible = false areaSoak.Active = true local draggingVertical = false local startYPos = nil verticalDragger.MouseEnter:connect(function () verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255) end) verticalDragger.MouseLeave:connect(function () verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) end) verticalDragger.MouseButton1Down:connect(function(x,y) draggingVertical = true areaSoak.Visible = true startYPos = y end) areaSoak.MouseButton1Up:connect(function ( ) draggingVertical = false areaSoak.Visible = false end) areaSoak.MouseMoved:connect(function(x,y) if not draggingVertical then return end local yDelta = y - startYPos if not control.ScrollDownButton.Visible and yDelta > 0 then return end if (widgetContainer.Size.Y.Offset + yDelta) < 150 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150) control.Size = UDim2.new (0,21,0,150) return end startYPos = y if widgetContainer.Size.Y.Offset + yDelta >= 0 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta) control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta ) end end) end local function switchMinimize() minimizeFrame.Visible = not minimizeFrame.Visible if scrollable then frame.Visible = not frame.Visible verticalDragger.Visible = not verticalDragger.Visible control.Visible = not control.Visible else widgetContainer.Visible = not widgetContainer.Visible end if minimizeFrame.Visible then minimizeButton.Text = "+" else minimizeButton.Text = "-" end end minimizeBigButton.MouseButton1Click:connect(function ( ) switchMinimize() end) minimizeButton.MouseButton1Click:connect(function( ) switchMinimize() end) if scrollable then return dragBar, frame, helpFrame, closeEvent else return dragBar, widgetContainer, helpFrame, closeEvent end end t.Help = function(funcNameOrFunc) --input argument can be a string or a function. Should return a description (of arguments and expected side effects) if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then return "Function CreatePropertyDropDownMenu. " .. "Arguments: (instance, propertyName, enumType). " .. "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'" end if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then return "Function CreateDropDownMenu. " .. "Arguments: (items, onItemSelected). " .. "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items" end if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then return "Function CreateMessageDialog. " .. "Arguments: (title, message, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button" end if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then return "Function CreateStyledMessageDialog. " .. "Arguments: (title, message, style, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm" end if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then return "Function GetFontHeight. " .. "Arguments: (font, fontSize). " .. "Side effect: returns the size in pixels of the given font + fontSize" end if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then end if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then return "Function CreateScrollingFrame. " .. "Arguments: (orderList, style) " .. "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)" end if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then return "Function CreateTrueScrollingFrame. " .. "Arguments: (nil) " .. "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit." end if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then return "Function AutoTruncateTextObject. " .. "Arguments: (textLabel) " .. "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument" end if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then return "Function CreateSlider. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then return "Function CreateSliderNew. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then return "Function CreateLoadingFrame. " .. "Arguments: (name, size, position) " .. "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog." end if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then return "Function CreateTerrainMaterialSelector. " .. "Arguments: (size, position) " .. "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected." end end local function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end end local function waitForProperty(instance, property) while not instance[property] do instance.Changed:wait() end end -- A Few Script Globals local gui = script.Parent.ControlFrame local helpButton = nil local updateCameraDropDownSelection = nil local updateVideoCaptureDropDownSelection = nil local tweenTime = 0.2 local mouseLockLookScreenUrl = "http://www.roblox.com/asset?id=54071825" local classicLookScreenUrl = "http://www.roblox.com/Asset?id=45915798" local hasGraphicsSlider = true local GraphicsQualityLevels = 10 local recordingVideo = false local currentMenuSelection = nil local lastMenuSelection = {} local defaultPosition = UDim2.new(0,0,0,0) local newGuiPlaces = {0,41324860} local centerDialogs = {} local mainShield = nil local inStudioMode = false local macClient = false local success, isMac = pcall(function() return not game.GuiService.IsWindows end) macClient = success and isMac local function Color3I(r,g,b) return Color3.new(r/255,g/255,b/255) end local function robloxLock(instance) end function resumeGameFunction(shield) shield.Settings:TweenPosition(UDim2.new(0.5, -262,-0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) delay(tweenTime,function() shield.Visible = false for i = 1, #centerDialogs do centerDialogs[i].Visible = false game.GuiService:RemoveCenterDialog(centerDialogs[i]) end settingsButton.Active = true currentMenuSelection = nil lastMenuSelection = {} end) end function goToMenu(container,menuName, moveDirection,size,position) if type(menuName) ~= "string" then return end table.insert(lastMenuSelection,currentMenuSelection) if menuName == "GameMainMenu" then lastMenuSelection = {} end local containerChildren = container:GetChildren() local selectedMenu = false for i = 1, #containerChildren do if containerChildren[i].Name == menuName then containerChildren[i].Visible = true currentMenuSelection = {container = container,name = menuName, direction = moveDirection, lastSize = size} selectedMenu = true if size and position then containerChildren[i]:TweenSizeAndPosition(size,position,Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) elseif size then containerChildren[i]:TweenSizeAndPosition(size,UDim2.new(0.5,-size.X.Offset/2,0.5,-size.Y.Offset/2),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) else containerChildren[i]:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) end else if moveDirection == "left" then containerChildren[i]:TweenPosition(UDim2.new(-1,-525,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) elseif moveDirection == "right" then containerChildren[i]:TweenPosition(UDim2.new(1,525,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) elseif moveDirection == "up" then containerChildren[i]:TweenPosition(UDim2.new(0,0,-1,-400),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) elseif moveDirection == "down" then containerChildren[i]:TweenPosition(UDim2.new(0,0,1,400),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) end delay(tweenTime,function() containerChildren[i].Visible = false end) end end end function resetLocalCharacter() local player = game.Players.LocalPlayer if player then if player.Character and player.Character:FindFirstChild("Humanoid") then player.Character.Humanoid.Health = 0 end end end local function createTextButton(text,style,fontSize,buttonSize,buttonPosition) local newTextButton = Instance.new("TextButton") newTextButton.Font = Enum.Font.Arial newTextButton.FontSize = fontSize newTextButton.Size = buttonSize newTextButton.Position = buttonPosition newTextButton.Style = style newTextButton.TextColor3 = Color3.new(1,1,1) newTextButton.Text = text return newTextButton end local function CreateTextButtons(frame, buttons, yPos, ySize) if #buttons < 1 then error("Must have more than one button") end local buttonNum = 1 local buttonObjs = {} local function toggleSelection(button) for i, obj in ipairs(buttonObjs) do if obj == button then obj.Style = Enum.ButtonStyle.RobloxButtonDefault else obj.Style = Enum.ButtonStyle.RobloxButton end end end for i, obj in ipairs(buttons) do local button = Instance.new("TextButton") button.Name = "Button" .. buttonNum button.Font = Enum.Font.Arial button.FontSize = Enum.FontSize.Size18 button.AutoButtonColor = true button.Style = Enum.ButtonStyle.RobloxButton button.Text = obj.Text button.TextColor3 = Color3.new(1,1,1) button.MouseButton1Click:connect(function() toggleSelection(button) obj.Function() end) button.Parent = frame buttonObjs[buttonNum] = button buttonNum = buttonNum + 1 end toggleSelection(buttonObjs[1]) local numButtons = buttonNum-1 if numButtons == 1 then frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset) elseif numButtons == 2 then frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset) frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset) frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset) elseif numButtons >= 3 then local spacing = .1 / numButtons local buttonSize = .9 / numButtons buttonNum = 1 while buttonNum <= numButtons do buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset) buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset) buttonNum = buttonNum + 1 end end end function setRecordGui(recording, stopRecordButton, recordVideoButton) if recording then stopRecordButton.Visible = true recordVideoButton.Text = "Stop Recording" else stopRecordButton.Visible = false recordVideoButton.Text = "Record Video" end end function recordVideoClick(recordVideoButton, stopRecordButton) recordingVideo = not recordingVideo setRecordGui(recordingVideo, stopRecordButton, recordVideoButton) end function backToGame(buttonClicked, shield, settingsButton) buttonClicked.Parent.Parent.Parent.Parent.Visible = false shield.Visible = false for i = 1, #centerDialogs do game.GuiService:RemoveCenterDialog(centerDialogs[i]) centerDialogs[i].Visible = false end centerDialogs = {} game.GuiService:RemoveCenterDialog(shield) settingsButton.Active = true end function setDisabledState(guiObject) if not guiObject then return end if guiObject:IsA("TextLabel") then guiObject.TextTransparency = 0.9 elseif guiObject:IsA("TextButton") then guiObject.TextTransparency = 0.9 guiObject.Active = false else if guiObject["ClassName"] then print("setDisabledState() got object of unsupported type. object type is ",guiObject.ClassName) end end end local function createHelpDialog(baseZIndex) if helpButton == nil then if gui:FindFirstChild("TopLeftControl") and gui.TopLeftControl:FindFirstChild("Help") then helpButton = gui.TopLeftControl.Help elseif gui:FindFirstChild("BottomRightControl") and gui.BottomRightControl:FindFirstChild("Help") then helpButton = gui.BottomRightControl.Help end end local shield = Instance.new("Frame") shield.Name = "HelpDialogShield" shield.Active = true shield.Visible = false shield.Size = UDim2.new(1,0,1,0) shield.BackgroundColor3 = Color3I(51,51,51) shield.BorderColor3 = Color3I(27,42,53) shield.BackgroundTransparency = 0.4 shield.ZIndex = baseZIndex + 1 shield.Parent = gui local helpDialog = Instance.new("Frame") helpDialog.Name = "HelpDialog" helpDialog.Style = Enum.FrameStyle.RobloxRound helpDialog.Position = UDim2.new(.2, 0, .2, 0) helpDialog.Size = UDim2.new(0.6, 0, 0.6, 0) helpDialog.Active = true helpDialog.Parent = shield local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = "Keyboard & Mouse Controls" titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.Position = UDim2.new(0, 0, 0.025, 0) titleLabel.Size = UDim2.new(1, 0, 0, 40) titleLabel.TextColor3 = Color3.new(1,1,1) titleLabel.BackgroundTransparency = 1 titleLabel.Parent = helpDialog local buttonRow = Instance.new("Frame") buttonRow.Name = "Buttons" buttonRow.Position = UDim2.new(0.1, 0, .07, 40) buttonRow.Size = UDim2.new(0.8, 0, 0, 45) buttonRow.BackgroundTransparency = 1 buttonRow.Parent = helpDialog local imageFrame = Instance.new("Frame") imageFrame.Name = "ImageFrame" imageFrame.Position = UDim2.new(0.05, 0, 0.075, 80) imageFrame.Size = UDim2.new(0.9, 0, .9, -120) imageFrame.BackgroundTransparency = 1 imageFrame.Parent = helpDialog local layoutFrame = Instance.new("Frame") layoutFrame.Name = "LayoutFrame" layoutFrame.Position = UDim2.new(0.5, 0, 0, 0) layoutFrame.Size = UDim2.new(1.5, 0, 1, 0) layoutFrame.BackgroundTransparency = 1 layoutFrame.SizeConstraint = Enum.SizeConstraint.RelativeYY layoutFrame.Parent = imageFrame local image = Instance.new("ImageLabel") image.Name = "Image" if UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then image.Image = mouseLockLookScreenUrl else image.Image = classicLookScreenUrl end image.Position = UDim2.new(-0.5, 0, 0, 0) image.Size = UDim2.new(1, 0, 1, 0) image.BackgroundTransparency = 1 image.Parent = layoutFrame local buttons = {} buttons[1] = {} buttons[1].Text = "Look" buttons[1].Function = function() if UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then image.Image = mouseLockLookScreenUrl else image.Image = classicLookScreenUrl end end buttons[2] = {} buttons[2].Text = "Move" buttons[2].Function = function() image.Image = "http://www.roblox.com/Asset?id=45915811" end buttons[3] = {} buttons[3].Text = "Gear" buttons[3].Function = function() image.Image = "http://www.roblox.com/Asset?id=45917596" end buttons[4] = {} buttons[4].Text = "Zoom" buttons[4].Function = function() image.Image = "http://www.roblox.com/Asset?id=45915825" end CreateTextButtons(buttonRow, buttons, UDim.new(0, 0), UDim.new(1,0)) -- set up listeners for type of mouse mode, but keep constructing gui at same time delay(0, function() waitForChild(gui,"UserSettingsShield") waitForChild(gui.UserSettingsShield,"Settings") waitForChild(gui.UserSettingsShield.Settings,"SettingsStyle") waitForChild(gui.UserSettingsShield.Settings.SettingsStyle, "GameSettingsMenu") waitForChild(gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu, "CameraField") waitForChild(gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu.CameraField, "DropDownMenuButton") gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu.CameraField.DropDownMenuButton.Changed:connect(function(prop) if prop ~= "Text" then return end if buttonRow.Button1.Style == Enum.ButtonStyle.RobloxButtonDefault then -- only change if this is the currently selected panel if gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu.CameraField.DropDownMenuButton.Text == "Classic" then image.Image = classicLookScreenUrl else image.Image = mouseLockLookScreenUrl end end end) end) local okBtn = Instance.new("TextButton") okBtn.Name = "OkBtn" okBtn.Text = "OK" okBtn.Modal = true okBtn.Size = UDim2.new(0.3, 0, 0, 45) okBtn.Position = UDim2.new(0.35, 0, .975, -50) okBtn.Font = Enum.Font.Arial okBtn.FontSize = Enum.FontSize.Size18 okBtn.BackgroundTransparency = 1 okBtn.TextColor3 = Color3.new(1,1,1) okBtn.Style = Enum.ButtonStyle.RobloxButtonDefault okBtn.MouseButton1Click:connect( function() gui.HelpDialogShield.Visible = false end) okBtn.Parent = helpDialog return shield end local function createLeaveConfirmationMenu(baseZIndex,shield) local frame = Instance.new("Frame") frame.Name = "LeaveConfirmationMenu" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1,0,1,0) frame.Position = UDim2.new(0,0,2,400) frame.ZIndex = baseZIndex + 4 local yesButton = createTextButton("Leave",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,313,0.8,0)) yesButton.Name = "YesButton" yesButton.ZIndex = baseZIndex + 4 yesButton.Parent = frame yesButton.Modal = true yesButton:SetVerb("Exit") local noButton = createTextButton("Stay",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,90,0.8,0)) noButton.Name = "NoButton" noButton.Parent = frame noButton.ZIndex = baseZIndex + 4 noButton.MouseButton1Click:connect(function() goToMenu(shield.Settings.SettingsStyle,"GameMainMenu","down",UDim2.new(0,525,0,430)) shield.Settings:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) end) local leaveText = Instance.new("TextLabel") leaveText.Name = "LeaveText" leaveText.Text = "Leave this game?" leaveText.Size = UDim2.new(1,0,0.8,0) leaveText.TextWrap = true leaveText.TextColor3 = Color3.new(1,1,1) leaveText.Font = Enum.Font.ArialBold leaveText.FontSize = Enum.FontSize.Size36 leaveText.BackgroundTransparency = 1 leaveText.ZIndex = baseZIndex + 4 leaveText.Parent = frame return frame end local function createResetConfirmationMenu(baseZIndex,shield) local frame = Instance.new("Frame") frame.Name = "ResetConfirmationMenu" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1,0,1,0) frame.Position = UDim2.new(0,0,2,400) frame.ZIndex = baseZIndex + 4 frame.Parent = gui local yesButton = createTextButton("Reset",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,313,0,299)) yesButton.Name = "YesButton" yesButton.ZIndex = baseZIndex + 4 yesButton.Parent = frame yesButton.Modal = true yesButton.MouseButton1Click:connect(function() resumeGameFunction(shield) resetLocalCharacter() end) local noButton = createTextButton("Cancel",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,90,0,299)) noButton.Name = "NoButton" noButton.Parent = frame noButton.ZIndex = baseZIndex + 4 noButton.MouseButton1Click:connect(function() goToMenu(shield.Settings.SettingsStyle,"GameMainMenu","down",UDim2.new(0,525,0,430)) shield.Settings:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) end) local resetCharacterText = Instance.new("TextLabel") resetCharacterText.Name = "ResetCharacterText" resetCharacterText.Text = "Are you sure you want to reset your character?" resetCharacterText.Size = UDim2.new(1,0,0.8,0) resetCharacterText.TextWrap = true resetCharacterText.TextColor3 = Color3.new(1,1,1) resetCharacterText.Font = Enum.Font.ArialBold resetCharacterText.FontSize = Enum.FontSize.Size36 resetCharacterText.BackgroundTransparency = 1 resetCharacterText.ZIndex = baseZIndex + 4 resetCharacterText.Parent = frame local fineResetCharacterText = resetCharacterText:Clone() fineResetCharacterText.Name = "FineResetCharacterText" fineResetCharacterText.Text = "You will be put back on a spawn point" fineResetCharacterText.Size = UDim2.new(0,303,0,18) fineResetCharacterText.Position = UDim2.new(0, 109, 0, 215) fineResetCharacterText.FontSize = Enum.FontSize.Size18 fineResetCharacterText.Parent = frame return frame end local function createGameMainMenu(baseZIndex, shield) local gameMainMenuFrame = Instance.new("Frame") gameMainMenuFrame.Name = "GameMainMenu" gameMainMenuFrame.BackgroundTransparency = 1 gameMainMenuFrame.Size = UDim2.new(1,0,1,0) gameMainMenuFrame.ZIndex = baseZIndex + 4 gameMainMenuFrame.Parent = script.Parent.UserSettingsShield.Settings.SettingsStyle -- GameMainMenu Children local gameMainMenuTitle = Instance.new("TextLabel") gameMainMenuTitle.Name = "Title" gameMainMenuTitle.Text = "Game Menu" gameMainMenuTitle.BackgroundTransparency = 1 gameMainMenuTitle.TextStrokeTransparency = 0 gameMainMenuTitle.Font = Enum.Font.ArialBold gameMainMenuTitle.FontSize = Enum.FontSize.Size36 gameMainMenuTitle.Size = UDim2.new(1,0,0,36) gameMainMenuTitle.Position = UDim2.new(0,0,0,4) gameMainMenuTitle.TextColor3 = Color3.new(1,1,1) gameMainMenuTitle.ZIndex = baseZIndex + 4 gameMainMenuTitle.Parent = gameMainMenuFrame local robloxHelpButton = createTextButton("Help",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,164,0,50),UDim2.new(0,82,0,256)) robloxHelpButton.Name = "HelpButton" robloxHelpButton.ZIndex = baseZIndex + 4 robloxHelpButton.Parent = gameMainMenuFrame helpButton = robloxHelpButton local helpDialog = createHelpDialog(baseZIndex) helpDialog.Parent = gui helpButton.MouseButton1Click:connect( function() helpDialog.Visible = true mainShield.Visible = false end) helpButton.Active = true local helpShortcut = Instance.new("TextLabel") helpShortcut.Name = "HelpShortcutText" helpShortcut.Text = "F1" helpShortcut.Visible = false helpShortcut.BackgroundTransparency = 1 helpShortcut.Font = Enum.Font.Arial helpShortcut.FontSize = Enum.FontSize.Size12 helpShortcut.Position = UDim2.new(0,85,0,0) helpShortcut.Size = UDim2.new(0,30,0,30) helpShortcut.TextColor3 = Color3.new(0,1,0) helpShortcut.ZIndex = baseZIndex + 4 helpShortcut.Parent = robloxHelpButton local screenshotButton = createTextButton("Screenshot",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,168,0,50),UDim2.new(0,254,0,256)) screenshotButton.Name = "ScreenshotButton" screenshotButton.ZIndex = baseZIndex + 4 screenshotButton.Parent = shield.Settings.SettingsStyle.GameMainMenu screenshotButton.Visible = not macClient screenshotButton:SetVerb("Screenshot") local screenshotShortcut = helpShortcut:clone() screenshotShortcut.Name = "ScreenshotShortcutText" screenshotShortcut.Text = "PrintSc" screenshotShortcut.Position = UDim2.new(0,118,0,0) screenshotShortcut.Visible = true screenshotShortcut.Parent = screenshotButton local recordVideoButton = createTextButton("Record Video",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,168,0,50),UDim2.new(0,254,0,306)) recordVideoButton.Name = "RecordVideoButton" recordVideoButton.ZIndex = baseZIndex + 4 recordVideoButton.Parent = gameMainMenuFrame recordVideoButton.Visible = not macClient recordVideoButton:SetVerb("RecordToggle") local recordVideoShortcut = helpShortcut:clone() recordVideoShortcut.Visible = hasGraphicsSlider recordVideoShortcut.Name = "RecordVideoShortcutText" recordVideoShortcut.Text = "F12" recordVideoShortcut.Position = UDim2.new(0,120,0,0) recordVideoShortcut.Parent = recordVideoButton local stopRecordButton = Instance.new("ImageButton") stopRecordButton.Name = "StopRecordButton" stopRecordButton.BackgroundTransparency = 1 stopRecordButton.Image = "rbxasset://textures/ui/RecordStop.png" stopRecordButton.Size = UDim2.new(0,59,0,27) stopRecordButton:SetVerb("RecordToggle") stopRecordButton.MouseButton1Click:connect(function() stopRecordButton.Visible = false end) recordVideoButton.MouseButton1Click:connect(function() stopRecordButton.Visible = true game.Players.LocalPlayer.PlayerGui.Menu.UserSettingsShield.Visible = false end) stopRecordButton.Visible = false stopRecordButton.Parent = gui local reportAbuseButton = createTextButton("Report Abuse",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,164,0,50),UDim2.new(0,82,0,306)) reportAbuseButton.Name = "ReportAbuseButton" reportAbuseButton.ZIndex = baseZIndex + 4 reportAbuseButton.Parent = gameMainMenuFrame reportAbuseButton.Active = true local leaveGameButton = createTextButton("Leave Game",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,358)) leaveGameButton.Name = "LeaveGameButton" leaveGameButton.ZIndex = baseZIndex + 4 leaveGameButton.Parent = gameMainMenuFrame local resumeGameButton = createTextButton("Resume Game",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,54)) resumeGameButton.Name = "resumeGameButton" resumeGameButton.ZIndex = baseZIndex + 4 resumeGameButton.Parent = gameMainMenuFrame resumeGameButton.Modal = true resumeGameButton.MouseButton1Click:connect(function() resumeGameFunction(shield) end) local gameSettingsButton = createTextButton("Game Settings",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,156)) gameSettingsButton.Name = "SettingsButton" gameSettingsButton.ZIndex = baseZIndex + 4 gameSettingsButton.Parent = gameMainMenuFrame if game:FindFirstChild("LoadingGuiService") and #game.LoadingGuiService:GetChildren() > 0 then local gameSettingsButton = createTextButton("Game Instructions",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,207)) gameSettingsButton.Name = "GameInstructions" gameSettingsButton.ZIndex = baseZIndex + 4 gameSettingsButton.Parent = gameMainMenuFrame gameSettingsButton.MouseButton1Click:connect(function() if game:FindFirstChild("Players") and game.Players["LocalPlayer"] then local loadingGui = game.Players.LocalPlayer:FindFirstChild("PlayerLoadingGui") if loadingGui then loadingGui.Visible = true end end end) end local resetButton = createTextButton("Reset Character",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,105)) resetButton.Name = "ResetButton" resetButton.ZIndex = baseZIndex + 4 resetButton.Parent = gameMainMenuFrame return gameMainMenuFrame end local function createGameSettingsMenu(baseZIndex, shield) local gameSettingsMenuFrame = Instance.new("Frame") gameSettingsMenuFrame.Name = "GameSettingsMenu" gameSettingsMenuFrame.BackgroundTransparency = 1 gameSettingsMenuFrame.Size = UDim2.new(1,0,1,0) gameSettingsMenuFrame.ZIndex = baseZIndex + 4 local title = Instance.new("TextLabel") title.Name = "Title" title.Text = "Settings" title.Size = UDim2.new(1,0,0,48) title.Position = UDim2.new(0,9,0,-9) title.Font = Enum.Font.ArialBold title.FontSize = Enum.FontSize.Size36 title.TextColor3 = Color3.new(1,1,1) title.ZIndex = baseZIndex + 4 title.BackgroundTransparency = 1 title.Parent = gameSettingsMenuFrame --[[ local studioText = Instance.new("TextLabel") studioText.Visible = false studioText.Name = "StudioText" studioText.Text = "Studio Mode" studioText.Size = UDim2.new(0,95,0,18) studioText.Position = UDim2.new(0,62,0,179) studioText.Font = Enum.Font.Arial studioText.FontSize = Enum.FontSize.Size18 studioText.TextColor3 = Color3.new(1,1,1) studioText.ZIndex = baseZIndex + 4 studioText.BackgroundTransparency = 1 studioText.Parent = gameSettingsMenuFrame local studioShortcut = fullscreenShortcut:clone() studioShortcut.Name = "StudioShortcutText" studioShortcut.Visible = false -- TODO: turn back on when f2 hack is fixed studioShortcut.Text = "F2" studioShortcut.Position = UDim2.new(0,154,0,175) studioShortcut.Parent = gameSettingsMenuFrame local studioCheckbox = nil --]] local itemTop = 35 ---------------------------------------------------------------------------------------------------- -- C A M E R A C O N T R O L S ---------------------------------------------------------------------------------------------------- if not touchClient then local cameraLabel = Instance.new("TextLabel") cameraLabel.Name = "CameraLabel" cameraLabel.Text = "Character & Camera Controls" cameraLabel.Font = Enum.Font.Arial cameraLabel.FontSize = Enum.FontSize.Size18 cameraLabel.Position = UDim2.new(0,31,0,itemTop + 6) cameraLabel.Size = UDim2.new(0,224,0,18) cameraLabel.TextColor3 = Color3I(255,255,255) cameraLabel.TextXAlignment = Enum.TextXAlignment.Left cameraLabel.BackgroundTransparency = 1 cameraLabel.ZIndex = baseZIndex + 4 cameraLabel.Parent = gameSettingsMenuFrame local mouseLockLabel = nil local enumItems = Enum.ControlMode:GetEnumItems() local enumNames = {} local enumNameToItem = {} for i,obj in ipairs(enumItems) do enumNames[i] = obj.Name enumNameToItem[obj.Name] = obj end local cameraDropDown cameraDropDown, updateCameraDropDownSelection = RbxGui.CreateDropDownMenu(enumNames, function(text) UserSettings().GameSettings.ControlMode = enumNameToItem[text] pcall(function() if mouseLockLabel and UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then mouseLockLabel.Visible = true elseif mouseLockLabel then mouseLockLabel.Visible = false end end) end) cameraDropDown.Name = "CameraField" cameraDropDown.ZIndex = baseZIndex + 4 cameraDropDown.DropDownMenuButton.ZIndex = baseZIndex + 4 cameraDropDown.DropDownMenuButton.Icon.ZIndex = baseZIndex + 4 cameraDropDown.Position = UDim2.new(0, 270, 0, itemTop) cameraDropDown.Size = UDim2.new(0,200,0,32) cameraDropDown.Parent = gameSettingsMenuFrame itemTop = itemTop + 35 end ---------------------------------------------------------------------------------------------------- -- V I D E O C A P T U R E S E T T I N G S ---------------------------------------------------------------------------------------------------- local syncVideoCaptureSetting = nil if not macClient and not touchClient then local videoCaptureLabel = Instance.new("TextLabel") videoCaptureLabel.Name = "VideoCaptureLabel" videoCaptureLabel.Text = "After Capturing Video" videoCaptureLabel.Font = Enum.Font.Arial videoCaptureLabel.FontSize = Enum.FontSize.Size18 videoCaptureLabel.Position = UDim2.new(0,32,0,itemTop + 6) videoCaptureLabel.Size = UDim2.new(0,164,0,18) videoCaptureLabel.BackgroundTransparency = 1 videoCaptureLabel.TextColor3 = Color3I(255,255,255) videoCaptureLabel.TextXAlignment = Enum.TextXAlignment.Left videoCaptureLabel.ZIndex = baseZIndex + 4 videoCaptureLabel.Parent = gameSettingsMenuFrame local videoNames = {} local videoNameToItem = {} videoNames[1] = "Just Save to Disk" videoNameToItem[videoNames[1]] = Enum.UploadSetting["Never"] videoNames[2] = "Upload to YouTube" videoNameToItem[videoNames[2]] = Enum.UploadSetting["Ask me first"] local videoCaptureDropDown = nil videoCaptureDropDown, updateVideoCaptureDropDownSelection = RbxGui.CreateDropDownMenu(videoNames, function(text) UserSettings().GameSettings.VideoUploadPromptBehavior = videoNameToItem[text] end) videoCaptureDropDown.Name = "VideoCaptureField" videoCaptureDropDown.ZIndex = baseZIndex + 4 videoCaptureDropDown.DropDownMenuButton.ZIndex = baseZIndex + 4 videoCaptureDropDown.DropDownMenuButton.Icon.ZIndex = baseZIndex + 4 videoCaptureDropDown.Position = UDim2.new(0, 270, 0, itemTop) videoCaptureDropDown.Size = UDim2.new(0,200,0,32) videoCaptureDropDown.Parent = gameSettingsMenuFrame syncVideoCaptureSetting = function() if UserSettings().GameSettings.VideoUploadPromptBehavior == Enum.UploadSetting["Never"] then updateVideoCaptureDropDownSelection(videoNames[1]) elseif UserSettings().GameSettings.VideoUploadPromptBehavior == Enum.UploadSetting["Ask me first"] then updateVideoCaptureDropDownSelection(videoNames[2]) else UserSettings().GameSettings.VideoUploadPromptBehavior = Enum.UploadSetting["Ask me first"] updateVideoCaptureDropDownSelection(videoNames[2]) end end itemTop = itemTop + 35 end ---------------------------------------------------------------------------------------------------- -- C U S T O M C A M E R A C O N T R O L S ---------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- -- F U L L S C R E E N M O D E ---------------------------------------------------------------------------------------------------- local fullscreenText = nil local fullscreenShortcut = nil local fullscreenCheckbox = nil if not touchClient then fullscreenText = Instance.new("TextLabel") fullscreenText.Name = "FullscreenText" fullscreenText.Text = "Fullscreen Mode" fullscreenText.Size = UDim2.new(0,124,0,18) fullscreenText.Position = UDim2.new(0,62,0,itemTop + 2) fullscreenText.Font = Enum.Font.Arial fullscreenText.FontSize = Enum.FontSize.Size18 fullscreenText.TextColor3 = Color3.new(1,1,1) fullscreenText.ZIndex = baseZIndex + 4 fullscreenText.BackgroundTransparency = 1 fullscreenText.Parent = gameSettingsMenuFrame fullscreenShortcut = Instance.new("TextLabel") fullscreenShortcut.Visible = hasGraphicsSlider fullscreenShortcut.Name = "FullscreenShortcutText" fullscreenShortcut.Text = "F11" fullscreenShortcut.BackgroundTransparency = 1 fullscreenShortcut.Font = Enum.Font.Arial fullscreenShortcut.FontSize = Enum.FontSize.Size12 fullscreenShortcut.Position = UDim2.new(0,186,0,itemTop - 4) fullscreenShortcut.Size = UDim2.new(0,30,0,30) fullscreenShortcut.TextColor3 = Color3.new(0,1,0) fullscreenShortcut.ZIndex = baseZIndex + 4 fullscreenShortcut.Parent = gameSettingsMenuFrame fullscreenCheckbox = createTextButton("",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,25,0,25),UDim2.new(0,30,0,itemTop)) fullscreenCheckbox.Name = "FullscreenCheckbox" fullscreenCheckbox.ZIndex = baseZIndex + 4 fullscreenCheckbox.Parent = gameSettingsMenuFrame fullscreenCheckbox:SetVerb("ToggleFullScreen") if UserSettings().GameSettings:InFullScreen() then fullscreenCheckbox.Text = "X" end if hasGraphicsSlider then UserSettings().GameSettings.FullscreenChanged:connect(function(isFullscreen) if isFullscreen then fullscreenCheckbox.Text = "X" else fullscreenCheckbox.Text = "" end end) else fullscreenCheckbox.MouseButton1Click:connect(function() if fullscreenCheckbox.Text == "" then fullscreenCheckbox.Text = "X" else fullscreenCheckbox.Text = "" end end) end end ---------------------------------------------------------------------------------------------------- -- G R A P H I C S S L I D E R ---------------------------------------------------------------------------------------------------- if hasGraphicsSlider then local qualityText = Instance.new("TextLabel") qualityText.Name = "QualityText" qualityText.Text = "Graphics Quality" qualityText.Size = UDim2.new(0,128,0,18) qualityText.Position = UDim2.new(0,30,0,239) qualityText.Font = Enum.Font.Arial qualityText.FontSize = Enum.FontSize.Size18 qualityText.TextColor3 = Color3.new(1,1,1) qualityText.ZIndex = baseZIndex + 4 qualityText.BackgroundTransparency = 1 qualityText.Parent = gameSettingsMenuFrame qualityText.Visible = not inStudioMode local autoText = qualityText:clone() autoText.Name = "AutoText" autoText.Text = "Auto" autoText.Position = UDim2.new(0,183,0,214) autoText.TextColor3 = Color3.new(128/255,128/255,128/255) autoText.Size = UDim2.new(0,34,0,18) autoText.Parent = gameSettingsMenuFrame autoText.Visible = not inStudioMode local fasterText = autoText:clone() fasterText.Name = "FasterText" fasterText.Text = "Faster" fasterText.Position = UDim2.new(0,185,0,274) fasterText.TextColor3 = Color3.new(95,95,95) fasterText.FontSize = Enum.FontSize.Size14 fasterText.Parent = gameSettingsMenuFrame fasterText.Visible = not inStudioMode local fasterShortcut = fullscreenShortcut:clone() fasterShortcut.Name = "FasterShortcutText" fasterShortcut.Text = "F10 + Shift" fasterShortcut.Position = UDim2.new(0,185,0,283) fasterShortcut.Parent = gameSettingsMenuFrame fasterShortcut.Visible = not inStudioMode local betterQualityText = autoText:clone() betterQualityText.Name = "BetterQualityText" betterQualityText.Text = "Better Quality" betterQualityText.TextWrap = true betterQualityText.Size = UDim2.new(0,41,0,28) betterQualityText.Position = UDim2.new(0,390,0,269) betterQualityText.TextColor3 = Color3.new(95,95,95) betterQualityText.FontSize = Enum.FontSize.Size14 betterQualityText.Parent = gameSettingsMenuFrame betterQualityText.Visible = not inStudioMode local betterQualityShortcut = fullscreenShortcut:clone() betterQualityShortcut.Name = "BetterQualityShortcut" betterQualityShortcut.Text = "F10" betterQualityShortcut.Position = UDim2.new(0,394,0,288) betterQualityShortcut.Parent = gameSettingsMenuFrame betterQualityShortcut.Visible = not inStudioMode local autoGraphicsButton = createTextButton("X",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,25,0,25),UDim2.new(0,187,0,239)) autoGraphicsButton.Name = "AutoGraphicsButton" autoGraphicsButton.ZIndex = baseZIndex + 4 autoGraphicsButton.Parent = gameSettingsMenuFrame autoGraphicsButton.Visible = not inStudioMode local graphicsSlider, graphicsLevel = RbxGui.CreateSlider(GraphicsQualityLevels,150,UDim2.new(0, 230, 0, 280)) -- graphics - 1 because slider starts at 1 instead of 0 graphicsSlider.Parent = gameSettingsMenuFrame graphicsSlider.Bar.ZIndex = baseZIndex + 4 graphicsSlider.Bar.Slider.ZIndex = baseZIndex + 5 graphicsSlider.Visible = not inStudioMode graphicsLevel.Value = math.floor((settings().Rendering:GetMaxQualityLevel() - 1)/2) local graphicsSetter = Instance.new("TextBox") graphicsSetter.Name = "GraphicsSetter" graphicsSetter.BackgroundColor3 = Color3.new(0,0,0) graphicsSetter.BorderColor3 = Color3.new(128/255,128/255,128/255) graphicsSetter.Size = UDim2.new(0,50,0,25) graphicsSetter.Position = UDim2.new(0,450,0,269) graphicsSetter.TextColor3 = Color3.new(1,1,1) graphicsSetter.Font = Enum.Font.Arial graphicsSetter.FontSize = Enum.FontSize.Size18 graphicsSetter.Text = "Auto" graphicsSetter.ZIndex = 1 graphicsSetter.TextWrap = true graphicsSetter.Parent = gameSettingsMenuFrame graphicsSetter.Visible = not inStudioMode local isAutoGraphics = true if not inStudioMode then isAutoGraphics = (UserSettings().GameSettings.SavedQualityLevel == Enum.SavedQualitySetting.Automatic) else settings().Rendering.EnableFRM = false end local listenToGraphicsLevelChange = true local function setAutoGraphicsGui(active) isAutoGraphics = active if active then autoGraphicsButton.Text = "X" betterQualityText.ZIndex = 1 betterQualityShortcut.ZIndex = 1 fasterShortcut.ZIndex = 1 fasterText.ZIndex = 1 graphicsSlider.Bar.ZIndex = 1 graphicsSlider.Bar.Slider.ZIndex = 1 graphicsSetter.ZIndex = 1 graphicsSetter.Text = "Auto" else autoGraphicsButton.Text = "" graphicsSlider.Bar.ZIndex = baseZIndex + 4 graphicsSlider.Bar.Slider.ZIndex = baseZIndex + 5 betterQualityShortcut.ZIndex = baseZIndex + 4 fasterShortcut.ZIndex = baseZIndex + 4 betterQualityText.ZIndex = baseZIndex + 4 fasterText.ZIndex = baseZIndex + 4 graphicsSetter.ZIndex = baseZIndex + 4 end end local function goToAutoGraphics() setAutoGraphicsGui(true) UserSettings().GameSettings.SavedQualityLevel = Enum.SavedQualitySetting.Automatic settings().Rendering.QualityLevel = Enum.QualityLevel.Automatic end local function setGraphicsQualityLevel(newLevel) local percentage = newLevel/GraphicsQualityLevels local newSetting = math.floor((settings().Rendering:GetMaxQualityLevel() - 1) * percentage) if newSetting == 20 then -- Level 20 is the same as level 21, except it doesn't render ambient occlusion newSetting = 21 elseif newLevel == 1 then -- make sure we can go to lowest settings (for terrible computers) newSetting = 1 elseif newSetting > settings().Rendering:GetMaxQualityLevel() then newSetting = settings().Rendering:GetMaxQualityLevel() - 1 end UserSettings().GameSettings.SavedQualityLevel = newLevel settings().Rendering.QualityLevel = newSetting end local function goToManualGraphics(explicitLevel) setAutoGraphicsGui(false) if explicitLevel then graphicsLevel.Value = explicitLevel else graphicsLevel.Value = math.floor((settings().Rendering.AutoFRMLevel/(settings().Rendering:GetMaxQualityLevel() - 1)) * GraphicsQualityLevels) end if explicitLevel == graphicsLevel.Value then -- make sure we are actually in right graphics mode setGraphicsQualityLevel(graphicsLevel.Value) end if not explicitLevel then UserSettings().GameSettings.SavedQualityLevel = graphicsLevel.Value end graphicsSetter.Text = tostring(graphicsLevel.Value) end local function showAutoGraphics() autoText.ZIndex = baseZIndex + 4 autoGraphicsButton.ZIndex = baseZIndex + 4 end local function hideAutoGraphics() autoText.ZIndex = 1 autoGraphicsButton.ZIndex = 1 end local function showManualGraphics() graphicsSlider.Bar.ZIndex = baseZIndex + 4 graphicsSlider.Bar.Slider.ZIndex = baseZIndex + 5 betterQualityShortcut.ZIndex = baseZIndex + 4 fasterShortcut.ZIndex = baseZIndex + 4 betterQualityText.ZIndex = baseZIndex + 4 fasterText.ZIndex = baseZIndex + 4 graphicsSetter.ZIndex = baseZIndex + 4 end local function hideManualGraphics() betterQualityText.ZIndex = 1 betterQualityShortcut.ZIndex = 1 fasterShortcut.ZIndex = 1 fasterText.ZIndex = 1 graphicsSlider.Bar.ZIndex = 1 graphicsSlider.Bar.Slider.ZIndex = 1 graphicsSetter.ZIndex = 1 end local function translateSavedQualityLevelToInt(savedQualityLevel) if savedQualityLevel == Enum.SavedQualitySetting.Automatic then return 0 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel1 then return 1 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel2 then return 2 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel3 then return 3 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel4 then return 4 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel5 then return 5 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel6 then return 6 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel7 then return 7 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel8 then return 8 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel9 then return 9 elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel10 then return 10 end end local function enableGraphicsWidget() settings().Rendering.EnableFRM = true isAutoGraphics = (UserSettings().GameSettings.SavedQualityLevel == Enum.SavedQualitySetting.Automatic) if isAutoGraphics then showAutoGraphics() goToAutoGraphics() else showAutoGraphics() showManualGraphics() goToManualGraphics(translateSavedQualityLevelToInt(UserSettings().GameSettings.SavedQualityLevel)) end end local function disableGraphicsWidget() hideManualGraphics() hideAutoGraphics() settings().Rendering.EnableFRM = false end graphicsSetter.FocusLost:connect(function() if isAutoGraphics then graphicsSetter.Text = tostring(graphicsLevel.Value) return end local newGraphicsValue = tonumber(graphicsSetter.Text) if newGraphicsValue == nil then graphicsSetter.Text = tostring(graphicsLevel.Value) return end if newGraphicsValue < 1 then newGraphicsValue = 1 elseif newGraphicsValue >= settings().Rendering:GetMaxQualityLevel() then newGraphicsValue = settings().Rendering:GetMaxQualityLevel() - 1 end graphicsLevel.Value = newGraphicsValue setGraphicsQualityLevel(graphicsLevel.Value) graphicsSetter.Text = tostring(graphicsLevel.Value) end) graphicsLevel.Changed:connect(function(prop) if isAutoGraphics then return end if not listenToGraphicsLevelChange then return end graphicsSetter.Text = tostring(graphicsLevel.Value) setGraphicsQualityLevel(graphicsLevel.Value) end) -- setup our graphic mode on load if inStudioMode or UserSettings().GameSettings.SavedQualityLevel == Enum.SavedQualitySetting.Automatic then if inStudioMode then settings().Rendering.EnableFRM = false disableGraphicsWidget() else settings().Rendering.EnableFRM = true goToAutoGraphics() end else settings().Rendering.EnableFRM = true goToManualGraphics(translateSavedQualityLevelToInt(UserSettings().GameSettings.SavedQualityLevel)) end autoGraphicsButton.MouseButton1Click:connect(function() if inStudioMode and not game.Players.LocalPlayer then return end if not isAutoGraphics then goToAutoGraphics() else goToManualGraphics(graphicsLevel.Value) end end) local lastUpdate = nil game.GraphicsQualityChangeRequest:connect(function(graphicsIncrease) if isAutoGraphics then return end -- only can set graphics in manual mode if graphicsIncrease then if (graphicsLevel.Value + 1) > GraphicsQualityLevels then return end graphicsLevel.Value = graphicsLevel.Value + 1 graphicsSetter.Text = tostring(graphicsLevel.Value) setGraphicsQualityLevel(graphicsLevel.Value) game:GetService("GuiService"):SendNotification("Graphics Quality", "Increased to (" .. graphicsSetter.Text .. ")", "", 2, function() end) else if (graphicsLevel.Value - 1) <= 0 then return end graphicsLevel.Value = graphicsLevel.Value - 1 graphicsSetter.Text = tostring(graphicsLevel.Value) setGraphicsQualityLevel(graphicsLevel.Value) game:GetService("GuiService"):SendNotification("Graphics Quality", "Decreased to (" .. graphicsSetter.Text .. ")", "", 2, function() end) end end) game.Players.PlayerAdded:connect(function(player) if player == game.Players.LocalPlayer and inStudioMode then enableGraphicsWidget() end end) game.Players.PlayerRemoving:connect(function(player) if player == game.Players.LocalPlayer and inStudioMode then disableGraphicsWidget() end end) studioCheckbox = createTextButton("",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,25,0,25),UDim2.new(0,30,0,176)) studioCheckbox.Name = "StudioCheckbox" studioCheckbox.ZIndex = baseZIndex + 4 --studioCheckbox.Parent = gameSettingsMenuFrame -- todo: enable when studio h4x aren't an issue anymore studioCheckbox:SetVerb("TogglePlayMode") studioCheckbox.Visible = false -- todo: enabled when studio h4x aren't an issue anymore local wasManualGraphics = (settings().Rendering.QualityLevel ~= Enum.QualityLevel.Automatic) if inStudioMode and not game.Players.LocalPlayer then studioCheckbox.Text = "X" disableGraphicsWidget() elseif inStudioMode then studioCheckbox.Text = "X" enableGraphicsWidget() end if hasGraphicsSlider then UserSettings().GameSettings.StudioModeChanged:connect(function(isStudioMode) inStudioMode = isStudioMode if isStudioMode then wasManualGraphics = (settings().Rendering.QualityLevel ~= Enum.QualityLevel.Automatic) goToAutoGraphics() studioCheckbox.Text = "X" autoGraphicsButton.ZIndex = 1 autoText.ZIndex = 1 else if wasManualGraphics then goToManualGraphics() end studioCheckbox.Text = "" autoGraphicsButton.ZIndex = baseZIndex + 4 autoText.ZIndex = baseZIndex + 4 end end) else studioCheckbox.MouseButton1Click:connect(function() if not studioCheckbox.Active then return end if studioCheckbox.Text == "" then studioCheckbox.Text = "X" else studioCheckbox.Text = "" end end) end end if game:FindFirstChild("NetworkClient") then -- we are playing online setDisabledState(studioText) setDisabledState(studioShortcut) setDisabledState(studioCheckbox) end ---------------------------------------------------------------------------------------------------- -- O K B U T T O N ---------------------------------------------------------------------------------------------------- local backButton if hasGraphicsSlider then backButton = createTextButton("OK",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,180,0,50),UDim2.new(0,170,0,330)) backButton.Modal = true else backButton = createTextButton("OK",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,180,0,50),UDim2.new(0,170,0,270)) backButton.Modal = true end backButton.Name = "BackButton" backButton.ZIndex = baseZIndex + 4 backButton.Parent = gameSettingsMenuFrame return gameSettingsMenuFrame end if LoadLibrary then RbxGui = t local baseZIndex = 0 if UserSettings then local createReportAbuseDialog = function() waitForChild(game,"Players") waitForProperty(game.Players, "LocalPlayer") local localPlayer = game.Players.LocalPlayer local reportAbuseButton waitForChild(script.Parent,"UserSettingsShield") waitForChild(script.Parent.UserSettingsShield, "Settings") waitForChild(script.Parent.UserSettingsShield.Settings,"SettingsStyle") waitForChild(script.Parent.UserSettingsShield.Settings.SettingsStyle,"GameMainMenu") waitForChild(script.Parent.UserSettingsShield.Settings.SettingsStyle.GameMainMenu, "ReportAbuseButton") reportAbuseButton = script.Parent.UserSettingsShield.Settings.SettingsStyle.GameMainMenu.ReportAbuseButton local shield = Instance.new("TextButton") shield.Name = "ReportAbuseShield" shield.Text = "" shield.AutoButtonColor = false shield.Active = true shield.Visible = false shield.Size = UDim2.new(1,0,1,0) shield.BackgroundColor3 = Color3I(51,51,51) shield.BorderColor3 = Color3I(27,42,53) shield.BackgroundTransparency = 0.4 shield.ZIndex = baseZIndex + 1 local closeAndResetDialgo local messageBoxButtons = {} messageBoxButtons[1] = {} messageBoxButtons[1].Text = "Ok" messageBoxButtons[1].Modal = true messageBoxButtons[1].Function = function() closeAndResetDialog() end local calmingMessageBox = RbxGui.CreateMessageDialog("Thanks for your report!", "Our moderators will review the chat logs and determine what happened. The other user is probably just trying to make you mad.\n\nIf anyone used swear words, inappropriate language, or threatened you in real life, please report them for Bad Words or Threats", messageBoxButtons) calmingMessageBox.Visible = false calmingMessageBox.Parent = shield local recordedMessageBox = RbxGui.CreateMessageDialog("Thanks for your report!","We've recorded your report for evaluation.", messageBoxButtons) recordedMessageBox.Visible = false recordedMessageBox.Parent = shield local normalMessageBox = RbxGui.CreateMessageDialog("Thanks for your report!", "Our moderators will review the chat logs and determine what happened.", messageBoxButtons) normalMessageBox.Visible = false normalMessageBox.Parent = shield local frame = Instance.new("Frame") frame.Name = "Settings" frame.Position = UDim2.new(0.5, -250, 0.5, -200) frame.Size = UDim2.new(0.0, 500, 0.0, 400) frame.BackgroundTransparency = 1 frame.Active = true frame.Parent = shield local settingsFrame = Instance.new("Frame") settingsFrame.Name = "ReportAbuseStyle" settingsFrame.Size = UDim2.new(1, 0, 1, 0) settingsFrame.Style = Enum.FrameStyle.RobloxRound settingsFrame.Active = true settingsFrame.ZIndex = baseZIndex + 1 settingsFrame.Parent = frame local title = Instance.new("TextLabel") title.Name = "Title" title.Text = "Report Abuse" title.TextColor3 = Color3I(221,221,221) title.Position = UDim2.new(0.5, 0, 0, 30) title.Font = Enum.Font.ArialBold title.FontSize = Enum.FontSize.Size36 title.ZIndex = baseZIndex + 2 title.Parent = settingsFrame local description = Instance.new("TextLabel") description.Name = "Description" description.Text = "This will send a complete report to a moderator. The moderator will review the chat log and take appropriate action." description.TextColor3 = Color3I(221,221,221) description.Position = UDim2.new(0, 0, 0, 55) description.Size = UDim2.new(1, 0, 0, 40) description.BackgroundTransparency = 1 description.Font = Enum.Font.Arial description.FontSize = Enum.FontSize.Size18 description.TextWrap = true description.ZIndex = baseZIndex + 2 description.TextXAlignment = Enum.TextXAlignment.Left description.TextYAlignment = Enum.TextYAlignment.Top description.Parent = settingsFrame local playerLabel = Instance.new("TextLabel") playerLabel.Name = "PlayerLabel" playerLabel.Text = "Which player?" playerLabel.BackgroundTransparency = 1 playerLabel.Font = Enum.Font.Arial playerLabel.FontSize = Enum.FontSize.Size18 playerLabel.Position = UDim2.new(0.025,0,0,100) playerLabel.Size = UDim2.new(0.4,0,0,36) playerLabel.TextColor3 = Color3I(255,255,255) playerLabel.TextXAlignment = Enum.TextXAlignment.Left playerLabel.ZIndex = baseZIndex + 2 playerLabel.Parent = settingsFrame local abusingPlayer = nil local abuse = nil local submitReportButton = nil local updatePlayerSelection = nil local createPlayersDropDown = function() local players = game:GetService("Players") local playerNames = {} local nameToPlayer = {} local children = players:GetChildren() local pos = 1 if children then for i, player in ipairs(children) do if player:IsA("Player") and player ~= localPlayer then playerNames[pos] = player.Name nameToPlayer[player.Name] = player pos = pos + 1 end end end local playerDropDown = nil playerDropDown, updatePlayerSelection = RbxGui.CreateDropDownMenu(playerNames, function(playerName) abusingPlayer = nameToPlayer[playerName] if abuse and abusingPlayer then submitReportButton.Active = true end end) playerDropDown.Name = "PlayersComboBox" playerDropDown.ZIndex = baseZIndex + 2 playerDropDown.Position = UDim2.new(.425, 0, 0, 102) playerDropDown.Size = UDim2.new(.55,0,0,32) return playerDropDown end local abuseLabel = Instance.new("TextLabel") abuseLabel.Name = "AbuseLabel" abuseLabel.Text = "Type of Abuse:" abuseLabel.Font = Enum.Font.Arial abuseLabel.BackgroundTransparency = 1 abuseLabel.FontSize = Enum.FontSize.Size18 abuseLabel.Position = UDim2.new(0.025,0,0,140) abuseLabel.Size = UDim2.new(0.4,0,0,36) abuseLabel.TextColor3 = Color3I(255,255,255) abuseLabel.TextXAlignment = Enum.TextXAlignment.Left abuseLabel.ZIndex = baseZIndex + 2 abuseLabel.Parent = settingsFrame local abuses = {"Swearing","Bullying","Scamming","Dating","Cheating/Exploiting","Personal Questions","Offsite Links","Bad Model or Script","Bad Username"} local abuseDropDown, updateAbuseSelection = RbxGui.CreateDropDownMenu(abuses, function(abuseText) abuse = abuseText if abuse and abusingPlayer then submitReportButton.Active = true end end, true) abuseDropDown.Name = "AbuseComboBox" abuseDropDown.ZIndex = baseZIndex + 2 abuseDropDown.Position = UDim2.new(0.425, 0, 0, 142) abuseDropDown.Size = UDim2.new(0.55,0,0,32) abuseDropDown.Parent = settingsFrame local shortDescriptionLabel = Instance.new("TextLabel") shortDescriptionLabel.Name = "ShortDescriptionLabel" shortDescriptionLabel.Text = "Short Description: (optional)" shortDescriptionLabel.Font = Enum.Font.Arial shortDescriptionLabel.FontSize = Enum.FontSize.Size18 shortDescriptionLabel.Position = UDim2.new(0.025,0,0,180) shortDescriptionLabel.Size = UDim2.new(0.95,0,0,36) shortDescriptionLabel.TextColor3 = Color3I(255,255,255) shortDescriptionLabel.TextXAlignment = Enum.TextXAlignment.Left shortDescriptionLabel.BackgroundTransparency = 1 shortDescriptionLabel.ZIndex = baseZIndex + 2 shortDescriptionLabel.Parent = settingsFrame local shortDescriptionWrapper = Instance.new("Frame") shortDescriptionWrapper.Name = "ShortDescriptionWrapper" shortDescriptionWrapper.Position = UDim2.new(0.025,0,0,220) shortDescriptionWrapper.Size = UDim2.new(0.95,0,1,-310) shortDescriptionWrapper.BackgroundColor3 = Color3I(0,0,0) shortDescriptionWrapper.BorderSizePixel = 0 shortDescriptionWrapper.ZIndex = baseZIndex + 2 shortDescriptionWrapper.Parent = settingsFrame local shortDescriptionBox = Instance.new("TextBox") shortDescriptionBox.Name = "TextBox" shortDescriptionBox.Text = "" shortDescriptionBox.ClearTextOnFocus = false shortDescriptionBox.Font = Enum.Font.Arial shortDescriptionBox.FontSize = Enum.FontSize.Size18 shortDescriptionBox.Position = UDim2.new(0,3,0,3) shortDescriptionBox.Size = UDim2.new(1,-6,1,-6) shortDescriptionBox.TextColor3 = Color3I(255,255,255) shortDescriptionBox.TextXAlignment = Enum.TextXAlignment.Left shortDescriptionBox.TextYAlignment = Enum.TextYAlignment.Top shortDescriptionBox.TextWrap = true shortDescriptionBox.BackgroundColor3 = Color3I(0,0,0) shortDescriptionBox.BorderSizePixel = 0 shortDescriptionBox.ZIndex = baseZIndex + 2 shortDescriptionBox.Parent = shortDescriptionWrapper submitReportButton = Instance.new("TextButton") submitReportButton.Name = "SubmitReportBtn" submitReportButton.Active = false submitReportButton.Modal = true submitReportButton.Font = Enum.Font.Arial submitReportButton.FontSize = Enum.FontSize.Size18 submitReportButton.Position = UDim2.new(0.1, 0, 1, -80) submitReportButton.Size = UDim2.new(0.35,0,0,50) submitReportButton.AutoButtonColor = true submitReportButton.Style = Enum.ButtonStyle.RobloxButtonDefault submitReportButton.Text = "Submit Report" submitReportButton.TextColor3 = Color3I(255,255,255) submitReportButton.ZIndex = baseZIndex + 2 submitReportButton.Parent = settingsFrame submitReportButton.MouseButton1Click:connect(function() if submitReportButton.Active then if abuse and abusingPlayer then frame.Visible = false game.Players:ReportAbuse(abusingPlayer, abuse, shortDescriptionBox.Text) if abuse == "Cheating/Exploiting" then recordedMessageBox.Visible = true elseif abuse == "Bullying" or abuse == "Swearing" then calmingMessageBox.Visible = true else normalMessageBox.Visible = true end else closeAndResetDialog() end end end) local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelBtn" cancelButton.Font = Enum.Font.Arial cancelButton.FontSize = Enum.FontSize.Size18 cancelButton.Position = UDim2.new(0.55, 0, 1, -80) cancelButton.Size = UDim2.new(0.35,0,0,50) cancelButton.AutoButtonColor = true cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault cancelButton.Text = "Cancel" cancelButton.TextColor3 = Color3I(255,255,255) cancelButton.ZIndex = baseZIndex + 2 cancelButton.Parent = settingsFrame closeAndResetDialog = function() settingsButton.Active = true currentMenuSelection = nil lastMenuSelection = {} --Delete old player combo box local oldComboBox = settingsFrame:FindFirstChild("PlayersComboBox") if oldComboBox then oldComboBox.Parent = nil end abusingPlayer = nil updatePlayerSelection(nil) abuse = nil updateAbuseSelection(nil) submitReportButton.Active = false shortDescriptionBox.Text = "" frame.Visible = true calmingMessageBox.Visible = false recordedMessageBox.Visible = false normalMessageBox.Visible = false shield.Visible = false reportAbuseButton.Active = true game.GuiService:RemoveCenterDialog(shield) end cancelButton.MouseButton1Click:connect(closeAndResetDialog) reportAbuseButton.MouseButton1Click:connect( function() createPlayersDropDown().Parent = settingsFrame table.insert(centerDialogs,shield) game.GuiService:AddCenterDialog(shield, Enum.CenterDialogType.ModalDialog, --ShowFunction function() reportAbuseButton.Active = true shield.Visible = true mainShield.Visible = false end, --HideFunction function() reportAbuseButton.Active = true shield.Visible = false end) end) return shield end local createSettingsDialog = function() waitForChild(gui,"BottomLeftControl") settingsButton = gui.BottomLeftControl:FindFirstChild("SettingsButton") if settingsButton == nil then settingsButton = Instance.new("ImageButton") settingsButton.Name = "SettingsButton" settingsButton.Image = "rbxasset://textures/ui/SettingsButton.png" settingsButton.BackgroundTransparency = 1 settingsButton.Active = false settingsButton.Size = UDim2.new(0,54,0,46) settingsButton.Position = UDim2.new(0,2,0,50) settingsButton.Parent = gui settingsButton.MouseButton1Click:connect(function() goToMenu(shield.Settings.SettingsStyle,"GameMainMenu","down",UDim2.new(0,525,0,430)) shield.Settings:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) end) end local shield = Instance.new("TextButton") shield.Text = "" shield.Name = "UserSettingsShield" shield.Active = true shield.AutoButtonColor = false shield.Visible = false shield.Size = UDim2.new(1,0,1,0) shield.BackgroundColor3 = Color3I(51,51,51) shield.BorderColor3 = Color3I(27,42,53) shield.BackgroundTransparency = 0.4 shield.ZIndex = baseZIndex + 2 shield.Parent = script.Parent mainShield = shield local frame = Instance.new("Frame") frame.Name = "Settings" frame.Position = UDim2.new(0.5, -262, -0.5, -200) frame.Size = UDim2.new(0, 525, 0, 430) frame.BackgroundTransparency = 1 frame.Active = true frame.Parent = shield local settingsFrame = Instance.new("Frame") settingsFrame.Name = "SettingsStyle" settingsFrame.Size = UDim2.new(1, 0, 1, 0) settingsFrame.Style = Enum.FrameStyle.RobloxRound settingsFrame.Active = true settingsFrame.ZIndex = baseZIndex + 3 settingsFrame.Parent = frame local gameSettingsMenu = createGameSettingsMenu(baseZIndex, shield) gameSettingsMenu.Parent = settingsFrame local gameReportAbuse = createReportAbuseDialog() gameReportAbuse.Parent = script.Parent local gameMainMenu = createGameMainMenu(baseZIndex, shield) gameMainMenu.Parent = settingsFrame gameMainMenu.ScreenshotButton.MouseButton1Click:connect(function() end) function localPlayerChange() gameMainMenu.ResetButton.Visible = game.Players.LocalPlayer if game.Players.LocalPlayer then settings().Rendering.EnableFRM = true elseif inStudioMode then settings().Rendering.EnableFRM = false end end gameMainMenu.ResetButton.Visible = game.Players.LocalPlayer if game.Players.LocalPlayer ~= nil then game.Players.LocalPlayer.Changed:connect(function() localPlayerChange() end) else delay(0,function() waitForProperty(game.Players,"LocalPlayer") gameMainMenu.ResetButton.Visible = game.Players.LocalPlayer game.Players.LocalPlayer.Changed:connect(function() localPlayerChange() end) end) end gameMainMenu.ReportAbuseButton.Visible = game:FindFirstChild("NetworkClient") if not gameMainMenu.ReportAbuseButton.Visible then game.ChildAdded:connect(function(child) if child:IsA("NetworkClient") then gameMainMenu.ReportAbuseButton.Visible = game:FindFirstChild("NetworkClient") end end) end gameMainMenu.ResetButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"ResetConfirmationMenu","up",UDim2.new(0,525,0,370)) end) gameMainMenu.LeaveGameButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"LeaveConfirmationMenu","down",UDim2.new(0,525,0,300)) end) local gameSettingsMenu = createGameSettingsMenu(baseZIndex, shield) gameSettingsMenu.Visible = false gameSettingsMenu.Parent = settingsFrame gameMainMenu.LeaveGameButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"LeaveConfirmationMenu","down",UDim2.new(0,525,0,300)) end) gameMainMenu.SettingsButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"GameSettingsMenu","left",UDim2.new(0,525,0,350)) end) gameSettingsMenu.BackButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430)) end) local resetConfirmationWindow = createResetConfirmationMenu(baseZIndex, shield) resetConfirmationWindow.Visible = false resetConfirmationWindow.Parent = settingsFrame local leaveConfirmationWindow = createLeaveConfirmationMenu(baseZIndex,shield) leaveConfirmationWindow.Visible = false leaveConfirmationWindow.Parent = settingsFrame settingsButton.MouseButton1Click:connect( function() game.GuiService:AddCenterDialog(shield, Enum.CenterDialogType.ModalDialog, --showFunction function() settingsButton.Active = false updateCameraDropDownSelection(UserSettings().GameSettings.ControlMode.Name) if syncVideoCaptureSetting then syncVideoCaptureSetting() end goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430)) shield.Visible = true settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) end, --hideFunction function() settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,-0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) shield.Visible = false settingsButton.Active = true end) end) return shield end delay(0, function() if settingsButton == nil then settingsButton = Instance.new("ImageButton") settingsButton.Name = "SettingsButton" settingsButton.Image = "rbxasset://textures/ui/SettingsButton.png" settingsButton.BackgroundTransparency = 1 settingsButton.Active = false settingsButton.Size = UDim2.new(0,54,0,46) settingsButton.Position = UDim2.new(0,2,0,50) settingsButton.Parent = gui.BottomLeftControl end local shield = Instance.new("TextButton") shield.Text = "" shield.Name = "UserSettingsShield" shield.Active = true shield.AutoButtonColor = false shield.Visible = false shield.Size = UDim2.new(1,0,1,0) shield.BackgroundColor3 = Color3I(51,51,51) shield.BorderColor3 = Color3I(27,42,53) shield.BackgroundTransparency = 0.4 shield.ZIndex = baseZIndex + 2 shield.Parent = script.Parent mainShield = shield local frame = Instance.new("Frame") frame.Name = "Settings" frame.Position = UDim2.new(0.5, -262, -0.5, -200) frame.Size = UDim2.new(0, 525, 0, 430) frame.BackgroundTransparency = 1 frame.Active = true frame.Parent = shield local settingsFrame = Instance.new("Frame") settingsFrame.Name = "SettingsStyle" settingsFrame.Size = UDim2.new(1, 0, 1, 0) settingsFrame.Style = Enum.FrameStyle.RobloxRound settingsFrame.Active = true settingsFrame.ZIndex = baseZIndex + 3 settingsFrame.Parent = frame local resetConfirmationWindow = createResetConfirmationMenu(baseZIndex, shield) resetConfirmationWindow.Visible = false resetConfirmationWindow.Parent = settingsFrame local leaveConfirmationWindow = createLeaveConfirmationMenu(baseZIndex,shield) leaveConfirmationWindow.Visible = false leaveConfirmationWindow.Parent = settingsFrame local gameMainMenu = createGameMainMenu(baseZIndex, shield) gameMainMenu.Parent = settingsFrame local gameSettingsMenu = createGameSettingsMenu(baseZIndex, shield) gameSettingsMenu.Visible = false gameSettingsMenu.Parent = settingsFrame gameMainMenu.SettingsButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"GameSettingsMenu","left",UDim2.new(0,525,0,350)) end) gameSettingsMenu.BackButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430)) end) gameMainMenu.ResetButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"ResetConfirmationMenu","up",UDim2.new(0,525,0,370)) end) gameMainMenu.LeaveGameButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"LeaveConfirmationMenu","up",UDim2.new(0,525,0,300)) end) gameMainMenu.ScreenshotButton.MouseButton1Click:connect(function() end) settingsButton.MouseButton1Click:connect(function() goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430)) shield.Visible = true shield.Active = true settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) end) game:GetService("GuiService").EscapeKeyPressed:connect(function() if shield.Visible == false then goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430)) shield.Visible = true shield.Active = true settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true) elseif shield.Visible == true then resumeGameFunction(shield) end end) gui.BottomLeftControl.SettingsButton.Active = true gui.BottomLeftControl.SettingsButton.Position = UDim2.new(0,2,0,-2) if mouseLockLabel and UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then mouseLockLabel.Visible = true elseif mouseLockLabel then mouseLockLabel.Visible = false end local createSaveDialogs = function() local shield = Instance.new("TextButton") shield.Text = "" shield.AutoButtonColor = false shield.Name = "SaveDialogShield" shield.Active = true shield.Visible = false shield.Size = UDim2.new(1,0,1,0) shield.BackgroundColor3 = Color3I(51,51,51) shield.BorderColor3 = Color3I(27,42,53) shield.BackgroundTransparency = 0.4 shield.ZIndex = baseZIndex+1 local clearAndResetDialog local save local saveLocal local dontSave local cancel local messageBoxButtons = {} messageBoxButtons[1] = {} messageBoxButtons[1].Text = "Save" messageBoxButtons[1].Style = Enum.ButtonStyle.RobloxButtonDefault messageBoxButtons[1].Function = function() save() end messageBoxButtons[2] = {} messageBoxButtons[2].Text = "Cancel" messageBoxButtons[2].Function = function() cancel() end messageBoxButtons[3] = {} messageBoxButtons[3].Text = "Don't Save" messageBoxButtons[3].Function = function() dontSave() end local saveDialogMessageBox = RbxGui.CreateStyledMessageDialog("Unsaved Changes", "Save your changes to ROBLOX before leaving?", "Confirm", messageBoxButtons) saveDialogMessageBox.Visible = true saveDialogMessageBox.Parent = shield local errorBoxButtons = {} local buttonOffset = 1 if game.LocalSaveEnabled then errorBoxButtons[buttonOffset] = {} errorBoxButtons[buttonOffset].Text = "Save to Disk" errorBoxButtons[buttonOffset].Function = function() saveLocal() end buttonOffset = buttonOffset + 1 end errorBoxButtons[buttonOffset] = {} errorBoxButtons[buttonOffset].Text = "Keep Playing" errorBoxButtons[buttonOffset].Function = function() cancel() end errorBoxButtons[buttonOffset+1] = {} errorBoxButtons[buttonOffset+1].Text = "Don't Save" errorBoxButtons[buttonOffset+1].Function = function() dontSave() end local errorDialogMessageBox = RbxGui.CreateStyledMessageDialog("Upload Failed", "Sorry, we could not save your changes to ROBLOX.", "Error", errorBoxButtons) errorDialogMessageBox.Visible = false errorDialogMessageBox.Parent = shield local spinnerDialog = Instance.new("Frame") spinnerDialog.Name = "SpinnerDialog" spinnerDialog.Style = Enum.FrameStyle.RobloxRound spinnerDialog.Size = UDim2.new(0, 350, 0, 150) spinnerDialog.Position = UDim2.new(.5, -175, .5, -75) spinnerDialog.Visible = false spinnerDialog.Active = true spinnerDialog.Parent = shield local waitingLabel = Instance.new("TextLabel") waitingLabel.Name = "WaitingLabel" waitingLabel.Text = "Saving to ROBLOX..." waitingLabel.Font = Enum.Font.ArialBold waitingLabel.FontSize = Enum.FontSize.Size18 waitingLabel.Position = UDim2.new(0.5, 25, 0.5, 0) waitingLabel.TextColor3 = Color3.new(1,1,1) waitingLabel.Parent = spinnerDialog local spinnerFrame = Instance.new("Frame") spinnerFrame.Name = "Spinner" spinnerFrame.Size = UDim2.new(0, 80, 0, 80) spinnerFrame.Position = UDim2.new(0.5, -150, 0.5, -40) spinnerFrame.BackgroundTransparency = 1 spinnerFrame.Parent = spinnerDialog local spinnerIcons = {} local spinnerNum = 1 while spinnerNum <= 8 do local spinnerImage = Instance.new("ImageLabel") spinnerImage.Name = "Spinner"..spinnerNum spinnerImage.Size = UDim2.new(0, 16, 0, 16) spinnerImage.Position = UDim2.new(.5+.3*math.cos(math.rad(45*spinnerNum)), -8, .5+.3*math.sin(math.rad(45*spinnerNum)), -8) spinnerImage.BackgroundTransparency = 1 spinnerImage.Image = "http://www.roblox.com/Asset?id=45880710" spinnerImage.Parent = spinnerFrame spinnerIcons[spinnerNum] = spinnerImage spinnerNum = spinnerNum + 1 end save = function() saveDialogMessageBox.Visible = false --Show the spinner dialog spinnerDialog.Visible = true local spin = true --Make it spin delay(0, function() local spinPos = 0 while spin do local pos = 0 while pos < 8 do if pos == spinPos or pos == ((spinPos+1)%8) then spinnerIcons[pos+1].Image = "http://www.roblox.com/Asset?id=45880668" else spinnerIcons[pos+1].Image = "http://www.roblox.com/Asset?id=45880710" end pos = pos + 1 end spinPos = (spinPos + 1) % 8 wait(0.2) end end) --Do the save while the spinner is going, function will wait local result = game:SaveToRoblox() if not result then --Try once more result = game:SaveToRoblox() end --Hide the spinner dialog spinnerDialog.Visible = false --And cause the delay thread to stop spin = false --Now process the result if result then --Success, close game:FinishShutdown(false) clearAndResetDialog() else --Failure, show the second dialog prompt errorDialogMessageBox.Visible = true end end saveLocal = function() errorDialogMessageBox.Visible = false game:FinishShutdown(true) clearAndResetDialog() end dontSave = function() saveDialogMessageBox.Visible = false errorDialogMessageBox.Visible = false game:FinishShutdown(false) clearAndResetDialog() end cancel = function() saveDialogMessageBox.Visible = false errorDialogMessageBox.Visible = false clearAndResetDialog() end clearAndResetDialog = function() saveDialogMessageBox.Visible = true errorDialogMessageBox.Visible = false spinnerDialog.Visible = false shield.Visible = false game.GuiService:RemoveCenterDialog(shield) end shield.Visible = false return shield end local createChatBar = function() --Only show a chat bar if we are a NetworkClient waitForChild(game, "NetworkClient") waitForChild(game, "Players") waitForProperty(game.Players, "LocalPlayer") local chatBar = Instance.new("Frame") chatBar.Name = "ChatBar" chatBar.Size = UDim2.new(1, 0, 0, 22) chatBar.Position = UDim2.new(0, 0, 1, 0) chatBar.BackgroundColor3 = Color3.new(0,0,0) chatBar.BorderSizePixel = 0 local chatBox = Instance.new("TextBox") chatBox.Text = "" chatBox.Visible = false chatBox.Size = UDim2.new(1,-4,1,0) chatBox.Position = UDim2.new(0,2,0,0) chatBox.TextXAlignment = Enum.TextXAlignment.Left chatBox.Font = Enum.Font.Arial chatBox.ClearTextOnFocus = false chatBox.FontSize = Enum.FontSize.Size14 chatBox.TextColor3 = Color3.new(1,1,1) chatBox.BackgroundTransparency = 1 --chatBox.Parent = chatBar local chatButton = Instance.new("TextButton") chatButton.Size = UDim2.new(1,-4,1,0) chatButton.Position = UDim2.new(0,2,0,0) chatButton.AutoButtonColor = false chatButton.Text = "To chat click here or press \"/\" key" chatButton.TextXAlignment = Enum.TextXAlignment.Left chatButton.Font = Enum.Font.Arial chatButton.FontSize = Enum.FontSize.Size14 chatButton.TextColor3 = Color3.new(1,1,1) chatButton.BackgroundTransparency = 1 --chatButton.Parent = chatBar local activateChat = function() if chatBox.Visible then return end chatButton.Visible = false chatBox.Text = "" chatBox.Visible = true chatBox:CaptureFocus() end chatButton.MouseButton1Click:connect(activateChat) local hotKeyEnabled = true local toggleHotKey = function(value) hotKeyEnabled = value end local guiService = game:GetService("GuiService") local newChatMode = pcall(function() --guiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey) --guiService.SpecialKeyPressed:connect(function(key) if key == Enum.SpecialKey.ChatHotkey and hotKeyEnabled then activateChat() end end) end) if not newChatMode then --guiService:AddKey("/") --guiService.KeyPressed:connect(function(key) if key == "/" and hotKeyEnabled then activateChat() end end) end chatBox.FocusLost:connect( function(enterPressed) if enterPressed then if chatBox.Text ~= "" then local str = chatBox.Text if string.sub(str, 1, 1) == '%' then game.Players:TeamChat(string.sub(str, 2)) else game.Players:Chat(str) end end end chatBox.Text = "" chatBox.Visible = false chatButton.Visible = true end) return chatBar, toggleHotKey end --Spawn a thread for the Save dialogs local isSaveDialogSupported = pcall(function() local var = game.LocalSaveEnabled end) if isSaveDialogSupported then delay(0, function() local saveDialogs = createSaveDialogs() saveDialogs.Parent = gui game.RequestShutdown = function() table.insert(centerDialogs,saveDialogs) game.GuiService:AddCenterDialog(saveDialogs, Enum.CenterDialogType.QuitDialog, --ShowFunction function() saveDialogs.Visible = true end, --HideFunction function() saveDialogs.Visible = false end) return true end end) end end) --Spawn a thread for the Report Abuse dialogs delay(0, function() createReportAbuseDialog().Parent = script.Parent waitForChild(gui,"UserSettingsShield") waitForChild(gui.UserSettingsShield, "Settings") waitForChild(gui.UserSettingsShield.Settings,"SettingsStyle") waitForChild(gui.UserSettingsShield.Settings.SettingsStyle,"GameMainMenu") waitForChild(gui.UserSettingsShield.Settings.SettingsStyle.GameMainMenu, "ReportAbuseButton") gui.UserSettingsShield.Settings.SettingsStyle.GameMainMenu.ReportAbuseButton.Active = true end) end --LoadLibrary if end Notifications false Init --rbxsig%DIuke4NUwBAugRhVX8zUGw0lNHksGNmUbxnUjItyfN6YfmsPF6w9OML1jkc9uaOFfrayWCJEroukxRmuvY9E5jVqOM8TBXgRXfyVoJsVQ+YRTUdE1U1Jn/X7+oh/W1LN8Ayn42HhTEVjEbpVV+BHAeQZpjZltXo5qyozomUTeQE=% --rbxassetid%48488398% function waitForProperty(instance, property) while not instance[property] do instance.Changed:wait() end end function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end end waitForProperty(game.Players,"LocalPlayer") waitForChild(script.Parent,"Popup") waitForChild(script.Parent.Popup,"AcceptButton") script.Parent.Popup.AcceptButton.Modal = true local localPlayer = game.Players.LocalPlayer local acceptedTeleport = Instance.new("IntValue") local friendRequestBlacklist = {} local teleportEnabled = true local makePopupInvisible = function() if script.Parent.Popup then script.Parent.Popup.Visible = false end end function makeFriend(fromPlayer,toPlayer) local popup = script.Parent:FindFirstChild("Popup") if popup == nil then return end -- there is no popup! if popup.Visible then return end -- currently popping something, abort! if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it! popup.PopupText.Text = "Accept Friend Request from " .. tostring(fromPlayer.Name) .. "?" popup.PopupImage.Image = "http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=352&y=352" showTwoButtons() popup.Visible = true popup.AcceptButton.Text = "Accept" popup.DeclineButton.Text = "Decline" popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true) local yesCon, noCon yesCon = popup.AcceptButton.MouseButton1Click:connect(function() popup.Visible = false toPlayer:RequestFriendship(fromPlayer) if yesCon then yesCon:disconnect() end if noCon then noCon:disconnect() end popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end) noCon = popup.DeclineButton.MouseButton1Click:connect(function() popup.Visible = false toPlayer:RevokeFriendship(fromPlayer) friendRequestBlacklist[fromPlayer] = true print("pop up blacklist") if yesCon then yesCon:disconnect() end if noCon then noCon:disconnect() end popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end) end game.Players.FriendRequestEvent:connect(function(fromPlayer,toPlayer,event) -- if this doesn't involve me, then do nothing if fromPlayer ~= localPlayer and toPlayer ~= localPlayer then return end if fromPlayer == localPlayer then if event == Enum.FriendRequestEvent.Accept then game:GetService("GuiService"):SendNotification("You are Friends", "With " .. toPlayer.Name .. "!", "http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(toPlayer.userId).."&x=48&y=48", 5, function() end) end elseif toPlayer == localPlayer then if event == Enum.FriendRequestEvent.Issue then if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it! game:GetService("GuiService"):SendNotification("Friend Request", "From " .. fromPlayer.Name, "http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=48&y=48", 8, function() makeFriend(fromPlayer,toPlayer) end) elseif event == Enum.FriendRequestEvent.Accept then game:GetService("GuiService"):SendNotification("You are Friends", "With " .. fromPlayer.Name .. "!", "http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=48&y=48", 5, function() end) end end end) function showOneButton() local popup = script.Parent:FindFirstChild("Popup") if popup then popup.OKButton.Visible = true popup.DeclineButton.Visible = false popup.AcceptButton.Visible = false end end function showTwoButtons() local popup = script.Parent:FindFirstChild("Popup") if popup then popup.DeclineButton.Visible = true popup.AcceptButton.Visible = true end end if teleportEnabled then game:GetService("TeleportService").ErrorCallback = function(message) local popup = script.Parent:FindFirstChild("Popup") showOneButton() popup.PopupText.Text = message local clickCon clickCon = popup.OKButton.MouseButton1Click:connect(function() if clickCon then clickCon:disconnect() end game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup")) popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end) game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog, --ShowFunction function() showOneButton() script.Parent:FindFirstChild("Popup").Visible = true popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true) end, --HideFunction function() popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end) end game:GetService("TeleportService").ConfirmationCallback = function(message, placeId, spawnName) local popup = script.Parent:FindFirstChild("Popup") popup.PopupText.Text = message popup.PopupImage.Image = "" local yesCon, noCon local function killCons() if yesCon then yesCon:disconnect() end if noCon then noCon:disconnect() end game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup")) popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end yesCon = popup.AcceptButton.MouseButton1Click:connect(function() killCons() local success, err = pcall(function() game:GetService("TeleportService"):TeleportImpl(placeId,spawnName) end) if not success then showOneButton() popup.PopupText.Text = err local clickCon clickCon = popup.OKButton.MouseButton1Click:connect(function() if clickCon then clickCon:disconnect() end game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup")) popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end) game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog, --ShowFunction function() showOneButton() script.Parent:FindFirstChild("Popup").Visible = true popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true) end, --HideFunction function() popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end) end end) noCon = popup.DeclineButton.MouseButton1Click:connect(function() killCons() local success = pcall(function() game:GetService("TeleportService"):TeleportCancel() end) end) local centerDialogSuccess = pcall(function() game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog, --ShowFunction function() showTwoButtons() popup.AcceptButton.Text = "Leave" popup.DeclineButton.Text = "Stay" script.Parent:FindFirstChild("Popup").Visible = true popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true) end, --HideFunction function() popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible()) end) end) if centerDialogSuccess == false then script.Parent:FindFirstChild("Popup").Visible = true popup.AcceptButton.Text = "Leave" popup.DeclineButton.Text = "Stay" popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true) end return true end end false PopupScript --rbxsig%kFJjpVHvWkJX02PNT/54It5wEJZscSSdzAhjsXr0WtGNy+idQIKiWTiMUqEANPv/ST8P3B5jNDPtM9SNqR53nY9P6B1PAS08ik0AquNdrWORpnFHwksP3xC2ysi2Y1LsByVO2Uj0FikBhLe1CAVmlmX22AqbO/qNaL26sftSHT0=% --rbxassetid%48488451% --build our gui local popupFrame = Instance.new("Frame") popupFrame.Position = UDim2.new(0.5,-165,0.5,-175) popupFrame.Size = UDim2.new(0,330,0,350) popupFrame.Style = Enum.FrameStyle.RobloxRound popupFrame.ZIndex = 4 popupFrame.Name = "Popup" popupFrame.Visible = false popupFrame.Parent = script.Parent local darken = popupFrame:clone() darken.Size = UDim2.new(1,16,1,16) darken.Position = UDim2.new(0,-8,0,-8) darken.Name = "Darken" darken.ZIndex = 1 darken.Parent = popupFrame local acceptButton = Instance.new("TextButton") acceptButton.Position = UDim2.new(0,20,0,270) acceptButton.Size = UDim2.new(0,100,0,50) acceptButton.Font = Enum.Font.ArialBold acceptButton.FontSize = Enum.FontSize.Size24 acceptButton.Style = Enum.ButtonStyle.RobloxButton acceptButton.TextColor3 = Color3.new(248/255,248/255,248/255) acceptButton.Text = "Yes" acceptButton.ZIndex = 5 acceptButton.Name = "AcceptButton" acceptButton.Parent = popupFrame local declineButton = acceptButton:clone() declineButton.Position = UDim2.new(1,-120,0,270) declineButton.Text = "No" declineButton.Name = "DeclineButton" declineButton.Parent = popupFrame local popupImage = Instance.new("ImageLabel") popupImage.BackgroundTransparency = 1 popupImage.Position = UDim2.new(0.5,-140,0,0) popupImage.Size = UDim2.new(0,280,0,280) popupImage.ZIndex = 3 popupImage.Name = "PopupImage" popupImage.Parent = popupFrame local backing = Instance.new("ImageLabel") backing.BackgroundTransparency = 1 backing.Size = UDim2.new(1,0,1,0) backing.Image = "http://www.roblox.com/asset/?id=47574181" backing.Name = "Backing" backing.ZIndex = 2 backing.Parent = popupImage local popupText = Instance.new("TextLabel") popupText.Name = "PopupText" popupText.Size = UDim2.new(1,0,0.8,0) popupText.Font = Enum.Font.ArialBold popupText.FontSize = Enum.FontSize.Size36 popupText.BackgroundTransparency = 1 popupText.Text = "Hello I'm a popup" popupText.TextColor3 = Color3.new(248/255,248/255,248/255) popupText.TextWrap = true popupText.ZIndex = 5 popupText.Parent = popupFrame script:remove() Playerlist false Init -- welcome to second version of playerlist!!! -- -- change log: -- 1 using a later version of playerlist which means more stability!!!!1 -- -- 2 stat names now work!!! -- -- made by iago#6808 -- local t = {} local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc) local eventConnection = nil --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away) local tryConnect = function() if game:IsAncestorOf(parentInstance) then --Entering the world, make sure we are connected/synced if not eventConnection then eventConnection = instance[event]:connect(signalFunc) if syncFunc then syncFunc() end end else --Probably leaving the world, so disconnect for now if eventConnection then eventConnection:disconnect() if removeFunc then removeFunc() end end end end --Hook it up to ancestryChanged signal local connection = parentInstance.AncestryChanged:connect(tryConnect) --Now connect us if we're already in the world tryConnect() return connection end local function getScreenGuiAncestor(instance) local localInstance = instance while localInstance and not localInstance:IsA("ScreenGui") do localInstance = localInstance.Parent end return localInstance end local function CreateButtons(frame, buttons, yPos, ySize) local buttonNum = 1 local buttonObjs = {} for i, obj in ipairs(buttons) do local button = Instance.new("TextButton") button.Name = "Button" .. buttonNum button.Font = Enum.Font.Arial button.FontSize = Enum.FontSize.Size18 button.AutoButtonColor = true button.Modal = true if obj["Style"] then button.Style = obj.Style else button.Style = Enum.ButtonStyle.RobloxButton end if obj["ZIndex"] then button.ZIndex = obj.ZIndex end button.Text = obj.Text button.TextColor3 = Color3.new(1,1,1) button.MouseButton1Click:connect(obj.Function) button.Parent = frame buttonObjs[buttonNum] = button buttonNum = buttonNum + 1 end local numButtons = buttonNum-1 if numButtons == 1 then frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset) elseif numButtons == 2 then frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset) frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset) frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset) frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset) elseif numButtons >= 3 then local spacing = .1 / numButtons local buttonSize = .9 / numButtons buttonNum = 1 while buttonNum <= numButtons do buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset) buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset) buttonNum = buttonNum + 1 end end end local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps) local newStep = steps - 1 --otherwise we really get one more step than we want local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X )) local wholeNum, remainder = math.modf(relativePosX * newStep) if remainder > 0.5 then wholeNum = wholeNum + 1 end relativePosX = wholeNum/newStep local result = math.ceil(relativePosX * newStep) if sliderPosition.Value ~= (result + 1) then --only update if we moved a step sliderPosition.Value = result + 1 slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end end local function cancelSlide(areaSoak) areaSoak.Visible = false if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end end t.CreateStyledMessageDialog = function(title, message, style, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0, 165) frame.Position = UDim2.new(0.25, 0, 0.5, -72.5) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local styleImage = Instance.new("ImageLabel") styleImage.Name = "StyleImage" styleImage.BackgroundTransparency = 1 styleImage.Position = UDim2.new(0,5,0,15) if style == "error" or style == "Error" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42565285" elseif style == "notify" or style == "Notify" then styleImage.Size = UDim2.new(0, 71, 0, 71) styleImage.Image = "http://www.roblox.com/asset/?id=42604978" elseif style == "confirm" or style == "Confirm" then styleImage.Size = UDim2.new(0, 74, 0, 76) styleImage.Image = "http://www.roblox.com/asset/?id=42557901" else return t.CreateMessageDialog(title,message,buttons) end styleImage.Parent = frame local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.TextStrokeTransparency = 0 titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 80, 0, 0) titleLabel.Size = UDim2.new(1, -80, 0, 40) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextStrokeTransparency = 0 messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 80, 0, 45) messageLabel.Size = UDim2.new(0.95, -80, 0, 55) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) ) return frame end t.CreateMessageDialog = function(title, message, buttons) local frame = Instance.new("Frame") frame.Size = UDim2.new(0.5, 0, 0.5, 0) frame.Position = UDim2.new(0.25, 0, 0.25, 0) frame.Name = "MessageDialog" frame.Active = true frame.Style = Enum.FrameStyle.RobloxRound local titleLabel = Instance.new("TextLabel") titleLabel.Name = "Title" titleLabel.Text = title titleLabel.BackgroundTransparency = 1 titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255) titleLabel.Position = UDim2.new(0, 0, 0, 0) titleLabel.Size = UDim2.new(1, 0, 0.15, 0) titleLabel.Font = Enum.Font.ArialBold titleLabel.FontSize = Enum.FontSize.Size36 titleLabel.TextXAlignment = Enum.TextXAlignment.Center titleLabel.TextYAlignment = Enum.TextYAlignment.Center titleLabel.Parent = frame local messageLabel = Instance.new("TextLabel") messageLabel.Name = "Message" messageLabel.Text = message messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255) messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0) messageLabel.Size = UDim2.new(0.95, 0, .55, 0) messageLabel.BackgroundTransparency = 1 messageLabel.Font = Enum.Font.Arial messageLabel.FontSize = Enum.FontSize.Size18 messageLabel.TextWrap = true messageLabel.TextXAlignment = Enum.TextXAlignment.Left messageLabel.TextYAlignment = Enum.TextYAlignment.Top messageLabel.Parent = frame CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0)) return frame end t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ) local baseZIndex = 0 if (type(baseZ) == "number") then baseZIndex = baseZ end local width = UDim.new(0, 100) local height = UDim.new(0, 32) local xPos = 0.055 local frame = Instance.new("Frame") local textColor = Color3.new(1,1,1) if (whiteSkin) then textColor = Color3.new(0.5, 0.5, 0.5) end frame.Name = "DropDownMenu" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(width, height) local dropDownMenu = Instance.new("TextButton") dropDownMenu.Name = "DropDownMenuButton" dropDownMenu.TextWrap = true dropDownMenu.TextColor3 = textColor dropDownMenu.Text = "Choose One" dropDownMenu.Font = Enum.Font.ArialBold dropDownMenu.FontSize = Enum.FontSize.Size18 dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center dropDownMenu.BackgroundTransparency = 1 dropDownMenu.AutoButtonColor = true if (whiteSkin) then dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else dropDownMenu.Style = Enum.ButtonStyle.RobloxButton end dropDownMenu.Size = UDim2.new(1,0,1,0) dropDownMenu.Parent = frame dropDownMenu.ZIndex = 2 + baseZIndex local dropDownIcon = Instance.new("ImageLabel") dropDownIcon.Name = "Icon" dropDownIcon.Active = false if (whiteSkin) then dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png" dropDownIcon.Size = UDim2.new(0,16,0,12) dropDownIcon.Position = UDim2.new(1,-17,0.5, -6) else dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894" dropDownIcon.Size = UDim2.new(0,11,0,6) dropDownIcon.Position = UDim2.new(1,-11,0.5, -2) end dropDownIcon.BackgroundTransparency = 1 dropDownIcon.Parent = dropDownMenu dropDownIcon.ZIndex = 2 + baseZIndex local itemCount = #items local dropDownItemCount = #items local useScrollButtons = false if dropDownItemCount > 6 then useScrollButtons = true dropDownItemCount = 6 end local droppedDownMenu = Instance.new("TextButton") droppedDownMenu.Name = "List" droppedDownMenu.Text = "" droppedDownMenu.BackgroundTransparency = 1 --droppedDownMenu.AutoButtonColor = true if (whiteSkin) then droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton else droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton end droppedDownMenu.Visible = false droppedDownMenu.Active = true --Blocks clicks droppedDownMenu.Position = UDim2.new(0,0,0,0) droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0) droppedDownMenu.Parent = frame droppedDownMenu.ZIndex = 2 + baseZIndex local choiceButton = Instance.new("TextButton") choiceButton.Name = "ChoiceButton" choiceButton.BackgroundTransparency = 1 choiceButton.BorderSizePixel = 0 choiceButton.Text = "ReplaceMe" choiceButton.TextColor3 = textColor choiceButton.TextXAlignment = Enum.TextXAlignment.Left choiceButton.TextYAlignment = Enum.TextYAlignment.Center choiceButton.BackgroundColor3 = Color3.new(1, 1, 1) choiceButton.Font = Enum.Font.Arial choiceButton.FontSize = Enum.FontSize.Size18 if useScrollButtons then choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0) else choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0) end choiceButton.TextWrap = true choiceButton.ZIndex = 2 + baseZIndex local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = true areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 3 + baseZIndex local dropDownSelected = false local scrollUpButton local scrollDownButton local scrollMouseCount = 0 local setZIndex = function(baseZIndex) droppedDownMenu.ZIndex = baseZIndex +1 if scrollUpButton then scrollUpButton.ZIndex = baseZIndex + 3 end if scrollDownButton then scrollDownButton.ZIndex = baseZIndex + 3 end local children = droppedDownMenu:GetChildren() if children then for i, child in ipairs(children) do if child.Name == "ChoiceButton" then child.ZIndex = baseZIndex + 2 elseif child.Name == "ClickCaptureButton" then child.ZIndex = baseZIndex end end end end local scrollBarPosition = 1 local updateScroll = function() if scrollUpButton then scrollUpButton.Active = scrollBarPosition > 1 end if scrollDownButton then scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount end local children = droppedDownMenu:GetChildren() if not children then return end local childNum = 1 for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then obj.Visible = false else obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0) obj.Visible = true end obj.TextColor3 = textColor obj.BackgroundTransparency = 1 childNum = childNum + 1 end end end local toggleVisibility = function() dropDownSelected = not dropDownSelected areaSoak.Visible = not areaSoak.Visible dropDownMenu.Visible = not dropDownSelected droppedDownMenu.Visible = dropDownSelected if dropDownSelected then setZIndex(4 + baseZIndex) else setZIndex(2 + baseZIndex) end if useScrollButtons then updateScroll() end end droppedDownMenu.MouseButton1Click:connect(toggleVisibility) local updateSelection = function(text) local foundItem = false local children = droppedDownMenu:GetChildren() local childNum = 1 if children then for i, obj in ipairs(children) do if obj.Name == "ChoiceButton" then if obj.Text == text then obj.Font = Enum.Font.ArialBold foundItem = true scrollBarPosition = childNum if (whiteSkin) then obj.TextColor3 = Color3.new(90/255,142/255,233/255) end else obj.Font = Enum.Font.Arial if (whiteSkin) then obj.TextColor3 = textColor end end childNum = childNum + 1 end end end if not text then dropDownMenu.Text = "Choose One" scrollBarPosition = 1 else if not foundItem then error("Invalid Selection Update -- " .. text) end if scrollBarPosition + dropDownItemCount > itemCount + 1 then scrollBarPosition = itemCount - dropDownItemCount + 1 end dropDownMenu.Text = text end end local function scrollDown() if scrollBarPosition + dropDownItemCount <= itemCount then scrollBarPosition = scrollBarPosition + 1 updateScroll() return true end return false end local function scrollUp() if scrollBarPosition > 1 then scrollBarPosition = scrollBarPosition - 1 updateScroll() return true end return false end if useScrollButtons then --Make some scroll buttons scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0) scrollUpButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollUpButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollUp() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollUp() == false then break end wait(0.1) end end) scrollUpButton.Parent = droppedDownMenu scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) scrollDownButton.Position = UDim2.new(1,-11,1,-11) scrollDownButton.Parent = droppedDownMenu scrollDownButton.MouseButton1Click:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseLeave:connect( function() scrollMouseCount = scrollMouseCount + 1 end) scrollDownButton.MouseButton1Down:connect( function() scrollMouseCount = scrollMouseCount + 1 scrollDown() local val = scrollMouseCount wait(0.5) while val == scrollMouseCount do if scrollDown() == false then break end wait(0.1) end end) local scrollbar = Instance.new("ImageLabel") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4) scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2) scrollbar.Parent = droppedDownMenu end for i,item in ipairs(items) do -- needed to maintain local scope for items in event listeners below local button = choiceButton:clone() button.Text = item button.Parent = droppedDownMenu if (whiteSkin) then button.TextColor3 = textColor end button.MouseButton1Click:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 updateSelection(item) onSelect(item) toggleVisibility() end) button.MouseEnter:connect(function() --Add Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(0,0,0) end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function() --Remove Highlight if (not whiteSkin) then button.TextColor3 = Color3.new(1,1,1) end button.BackgroundTransparency = 1 end) end --This does the initial layout of the buttons updateScroll() frame.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(frame) end end) dropDownMenu.MouseButton1Click:connect(toggleVisibility) areaSoak.MouseButton1Click:connect(toggleVisibility) return frame, updateSelection end t.CreatePropertyDropDownMenu = function(instance, property, enum) local items = enum:GetEnumItems() local names = {} local nameToItem = {} for i,obj in ipairs(items) do names[i] = obj.Name nameToItem[obj.Name] = obj end local frame local updateSelection frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end) ScopedConnect(frame, instance, "Changed", function(prop) if prop == property then updateSelection(instance[property].Name) end end, function() updateSelection(instance[property].Name) end) return frame end t.GetFontHeight = function(font, fontSize) if font == nil or fontSize == nil then error("Font and FontSize must be non-nil") end if font == Enum.Font.Legacy then if fontSize == Enum.FontSize.Size8 then return 12 elseif fontSize == Enum.FontSize.Size9 then return 14 elseif fontSize == Enum.FontSize.Size10 then return 15 elseif fontSize == Enum.FontSize.Size11 then return 17 elseif fontSize == Enum.FontSize.Size12 then return 18 elseif fontSize == Enum.FontSize.Size14 then return 21 elseif fontSize == Enum.FontSize.Size18 then return 27 elseif fontSize == Enum.FontSize.Size24 then return 36 elseif fontSize == Enum.FontSize.Size36 then return 54 elseif fontSize == Enum.FontSize.Size48 then return 72 else error("Unknown FontSize") end elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then if fontSize == Enum.FontSize.Size8 then return 8 elseif fontSize == Enum.FontSize.Size9 then return 9 elseif fontSize == Enum.FontSize.Size10 then return 10 elseif fontSize == Enum.FontSize.Size11 then return 11 elseif fontSize == Enum.FontSize.Size12 then return 12 elseif fontSize == Enum.FontSize.Size14 then return 14 elseif fontSize == Enum.FontSize.Size18 then return 18 elseif fontSize == Enum.FontSize.Size24 then return 24 elseif fontSize == Enum.FontSize.Size36 then return 36 elseif fontSize == Enum.FontSize.Size48 then return 48 else error("Unknown FontSize") end else error("Unknown Font " .. font) end end local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable) local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y for i, child in ipairs(guiObjects) do if child:IsA("TextLabel") or child:IsA("TextButton") then local isLabel = child:IsA("TextLabel") if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining) if child.TextFits and child.TextBounds.Y < pixelsRemaining then child.Visible = true if isLabel then child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"]) else child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"]) end while not child.TextFits do child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1) end pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if isLabel then pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"] else pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"] end else child.Visible = false pixelsRemaining = -1 end else --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y child.Visible = (pixelsRemaining >= 0) end end end t.LayoutGuiObjects = function(frame, guiObjects, settingsTable) if not frame:IsA("GuiObject") then error("Frame must be a GuiObject") end for i, child in ipairs(guiObjects) do if not child:IsA("GuiObject") then error("All elements that are layed out must be of type GuiObject") end end if not settingsTable then settingsTable = {} end if not settingsTable["TextLabelSizePadY"] then settingsTable["TextLabelSizePadY"] = 0 end if not settingsTable["TextLabelPositionPadY"] then settingsTable["TextLabelPositionPadY"] = 0 end if not settingsTable["TextButtonSizePadY"] then settingsTable["TextButtonSizePadY"] = 12 end if not settingsTable["TextButtonPositionPadY"] then settingsTable["TextButtonPositionPadY"] = 2 end --Wrapper frame takes care of styled objects local wrapperFrame = Instance.new("Frame") wrapperFrame.Name = "WrapperFrame" wrapperFrame.BackgroundTransparency = 1 wrapperFrame.Size = UDim2.new(1,0,1,0) wrapperFrame.Parent = frame for i, child in ipairs(guiObjects) do child.Parent = wrapperFrame end local recalculate = function() wait() layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(recalculate) layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable) end t.CreateSlider = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 4 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local bar = Instance.new("TextButton") bar.Text = "" bar.AutoButtonColor = false bar.Name = "Bar" bar.BackgroundColor3 = Color3.new(0,0,0) if type(width) == "number" then bar.Size = UDim2.new(0,width,0,5) else bar.Size = UDim2.new(0,200,0,5) end bar.BorderColor3 = Color3.new(95/255,95/255,95/255) bar.ZIndex = 2 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/Slider.png" slider.Position = UDim2.new(0,0,0.5,-10) slider.Size = UDim2.new(0,20,0,20) slider.ZIndex = 3 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (steps - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateSliderNew = function(steps,width,position) local sliderGui = Instance.new("Frame") sliderGui.Size = UDim2.new(1,0,1,0) sliderGui.BackgroundTransparency = 1 sliderGui.Name = "SliderGui" local sliderSteps = Instance.new("IntValue") sliderSteps.Name = "SliderSteps" sliderSteps.Value = steps sliderSteps.Parent = sliderGui local areaSoak = Instance.new("TextButton") areaSoak.Name = "AreaSoak" areaSoak.Text = "" areaSoak.BackgroundTransparency = 1 areaSoak.Active = false areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.Visible = false areaSoak.ZIndex = 6 sliderGui.AncestryChanged:connect(function(child,parent) if parent == nil then areaSoak.Parent = nil else areaSoak.Parent = getScreenGuiAncestor(sliderGui) end end) local sliderPosition = Instance.new("IntValue") sliderPosition.Name = "SliderPosition" sliderPosition.Value = 0 sliderPosition.Parent = sliderGui local id = math.random(1,100) local sliderBarImgHeight = 7 local sliderBarCapImgWidth = 4 local bar = Instance.new("ImageButton") bar.BackgroundTransparency = 1 bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png" bar.Name = "Bar" local displayWidth = 200 if type(width) == "number" then bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight) displayWidth = width - (sliderBarCapImgWidth * 2) else bar.Size = UDim2.new(0,200,0,sliderBarImgHeight) end bar.ZIndex = 3 bar.Parent = sliderGui if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then bar.Position = position end local barLeft = bar:clone() barLeft.Name = "BarLeft" barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png" barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight) barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset) barLeft.Parent = sliderGui barLeft.ZIndex = 3 local barRight = barLeft:clone() barRight.Name = "BarRight" barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png" barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset) barRight.Parent = sliderGui local fillLeft = barLeft:clone() fillLeft.Name = "FillLeft" fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png" fillLeft.Parent = sliderGui fillLeft.ZIndex = 4 local fill = fillLeft:clone() fill.Name = "Fill" fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png" fill.Parent = bar fill.ZIndex = 4 fill.Position = UDim2.new(0, 0, 0, 0) fill.Size = UDim2.new(0.5, 0, 1, 0) -- bar.Visible = false local slider = Instance.new("ImageButton") slider.Name = "Slider" slider.BackgroundTransparency = 1 slider.Image = "rbxasset://textures/ui/slider_new_tab.png" slider.Position = UDim2.new(0,0,0.5,-14) slider.Size = UDim2.new(0,28,0,28) slider.ZIndex = 5 slider.Parent = bar local areaSoakMouseMoveCon = nil areaSoak.MouseLeave:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) areaSoak.MouseButton1Up:connect(function() if areaSoak.Visible then cancelSlide(areaSoak) end end) slider.MouseButton1Down:connect(function() areaSoak.Visible = true if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) end) slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end) sliderPosition.Changed:connect(function(prop) sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value)) local relativePosX = (sliderPosition.Value - 1) / (steps - 1) slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset) fill.Size = UDim2.new(relativePosX, 0, 1, 0) end) bar.MouseButton1Down:connect(function(x,y) setSliderPos(x,slider,sliderPosition,bar,steps) end) return sliderGui, sliderPosition, sliderSteps end t.CreateTrueScrollingFrame = function() local lowY = nil local highY = nil local dragCon = nil local upCon = nil local internalChange = false local descendantsChangeConMap = {} local scrollingFrame = Instance.new("Frame") scrollingFrame.Name = "ScrollingFrame" scrollingFrame.Active = true scrollingFrame.Size = UDim2.new(1,0,1,0) scrollingFrame.ClipsDescendants = true local controlFrame = Instance.new("Frame") controlFrame.Name = "ControlFrame" controlFrame.BackgroundTransparency = 1 controlFrame.Size = UDim2.new(0,18,1,0) controlFrame.Position = UDim2.new(1,-20,0,0) controlFrame.Parent = scrollingFrame local scrollBottom = Instance.new("BoolValue") scrollBottom.Value = false scrollBottom.Name = "ScrollBottom" scrollBottom.Parent = controlFrame local scrollUp = Instance.new("BoolValue") scrollUp.Value = false scrollUp.Name = "scrollUp" scrollUp.Parent = controlFrame local scrollUpButton = Instance.new("TextButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.Text = "" scrollUpButton.AutoButtonColor = false scrollUpButton.BackgroundColor3 = Color3.new(0,0,0) scrollUpButton.BorderColor3 = Color3.new(1,1,1) scrollUpButton.BackgroundTransparency = 0.5 scrollUpButton.Size = UDim2.new(0,18,0,18) scrollUpButton.ZIndex = 2 scrollUpButton.Parent = controlFrame for i = 1, 6 do local triFrame = Instance.new("Frame") triFrame.BorderColor3 = Color3.new(1,1,1) triFrame.Name = "tri" .. tostring(i) triFrame.ZIndex = 3 triFrame.BackgroundTransparency = 0.5 triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0) triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1)) triFrame.Parent = scrollUpButton end scrollUpButton.MouseEnter:connect(function() scrollUpButton.BackgroundTransparency = 0.1 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.1 end end) scrollUpButton.MouseLeave:connect(function() scrollUpButton.BackgroundTransparency = 0.5 local upChildren = scrollUpButton:GetChildren() for i = 1, #upChildren do upChildren[i].BackgroundTransparency = 0.5 end end) local scrollDownButton = scrollUpButton:clone() scrollDownButton.Name = "ScrollDownButton" scrollDownButton.Position = UDim2.new(0,0,1,-18) local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1)) end scrollDownButton.MouseEnter:connect(function() scrollDownButton.BackgroundTransparency = 0.1 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.1 end end) scrollDownButton.MouseLeave:connect(function() scrollDownButton.BackgroundTransparency = 0.5 local downChildren = scrollDownButton:GetChildren() for i = 1, #downChildren do downChildren[i].BackgroundTransparency = 0.5 end end) scrollDownButton.Parent = controlFrame local scrollTrack = Instance.new("Frame") scrollTrack.Name = "ScrollTrack" scrollTrack.BackgroundTransparency = 1 scrollTrack.Size = UDim2.new(0,18,1,-38) scrollTrack.Position = UDim2.new(0,0,0,19) scrollTrack.Parent = controlFrame local scrollbar = Instance.new("TextButton") scrollbar.BackgroundColor3 = Color3.new(0,0,0) scrollbar.BorderColor3 = Color3.new(1,1,1) scrollbar.BackgroundTransparency = 0.5 scrollbar.AutoButtonColor = false scrollbar.Text = "" scrollbar.Active = true scrollbar.Name = "ScrollBar" scrollbar.ZIndex = 2 scrollbar.BackgroundTransparency = 0.5 scrollbar.Size = UDim2.new(0, 18, 0.1, 0) scrollbar.Position = UDim2.new(0,0,0,0) scrollbar.Parent = scrollTrack local scrollNub = Instance.new("Frame") scrollNub.Name = "ScrollNub" scrollNub.BorderColor3 = Color3.new(1,1,1) scrollNub.Size = UDim2.new(0,10,0,0) scrollNub.Position = UDim2.new(0.5,-5,0.5,0) scrollNub.ZIndex = 2 scrollNub.BackgroundTransparency = 0.5 scrollNub.Parent = scrollbar local newNub = scrollNub:clone() newNub.Position = UDim2.new(0.5,-5,0.5,-2) newNub.Parent = scrollbar local lastNub = scrollNub:clone() lastNub.Position = UDim2.new(0.5,-5,0.5,2) lastNub.Parent = scrollbar scrollbar.MouseEnter:connect(function() scrollbar.BackgroundTransparency = 0.1 scrollNub.BackgroundTransparency = 0.1 newNub.BackgroundTransparency = 0.1 lastNub.BackgroundTransparency = 0.1 end) scrollbar.MouseLeave:connect(function() scrollbar.BackgroundTransparency = 0.5 scrollNub.BackgroundTransparency = 0.5 newNub.BackgroundTransparency = 0.5 lastNub.BackgroundTransparency = 0.5 end) local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local function positionScrollBar(x,y,offset) local oldPos = scrollbar.Position if y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) return (oldPos ~= scrollbar.Position) end local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) return (oldPos ~= scrollbar.Position) end local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y if newScaleYPos + relativeSize > 1 then newScaleYPos = 1 - relativeSize scrollBottom.Value = true scrollUp.Value = false elseif newScaleYPos <= 0 then newScaleYPos = 0 scrollUp.Value = true scrollBottom.Value = false else scrollUp.Value = false scrollBottom.Value = false end scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0) return (oldPos ~= scrollbar.Position) end local function drillDownSetHighLow(instance) if not instance or not instance:IsA("GuiObject") then return end if instance == controlFrame then return end if instance:IsDescendantOf(controlFrame) then return end if not instance.Visible then return end if lowY and lowY > instance.AbsolutePosition.Y then lowY = instance.AbsolutePosition.Y elseif not lowY then lowY = instance.AbsolutePosition.Y end if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end local children = instance:GetChildren() for i = 1, #children do drillDownSetHighLow(children[i]) end end local function resetHighLow() local firstChildren = scrollingFrame:GetChildren() for i = 1, #firstChildren do drillDownSetHighLow(firstChildren[i]) end end local function recalculate() internalChange = true local percentFrame = 0 if scrollbar.Position.Y.Scale > 0 then if scrollbar.Visible then percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y) else percentFrame = 0 end end if percentFrame > 0.99 then percentFrame = 1 end local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame local guiChildren = scrollingFrame:GetChildren() for i = 1, #guiChildren do if guiChildren[i] ~= controlFrame then guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset, 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount) end end lowY = nil highY = nil resetHighLow() internalChange = false end local function setSliderSizeAndPosition() if not highY or not lowY then return end local totalYSpan = math.abs(highY - lowY) if totalYSpan == 0 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end return end local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan if percentShown >= 1 then scrollbar.Visible = false scrollDownButton.Visible = false scrollUpButton.Visible = false recalculate() else scrollbar.Visible = true scrollDownButton.Visible = true scrollUpButton.Visible = true scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0) end local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2) if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0) end if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0) end end local buttonScrollAmountPixels = 7 local reentrancyGuardScrollUp = false local function doScrollUp() if reentrancyGuardScrollUp then return end reentrancyGuardScrollUp = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollUp = false end local reentrancyGuardScrollDown = false local function doScrollDown() if reentrancyGuardScrollDown then return end reentrancyGuardScrollDown = true if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then recalculate() end reentrancyGuardScrollDown = false end local function scrollUp(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local function scrollDown(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end scrollbar.MouseButton1Down:connect(function(x,y) if scrollbar.Active then scrollStamp = tick() local mouseOffset = y - scrollbar.AbsolutePosition.y if dragCon then dragCon:disconnect() dragCon = nil end if upCon then upCon:disconnect() upCon = nil end local prevY = y local reentrancyGuardMouseScroll = false dragCon = mouseDrag.MouseMoved:connect(function(x,y) if reentrancyGuardMouseScroll then return end reentrancyGuardMouseScroll = true if positionScrollBar(x,y,mouseOffset) then recalculate() end reentrancyGuardMouseScroll = false end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect(function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect(function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) local function heightCheck(instance) if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y elseif not highY then highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y end setSliderSizeAndPosition() end local function highLowRecheck() local oldLowY = lowY local oldHighY = highY lowY = nil highY = nil resetHighLow() if (lowY ~= oldLowY) or (highY ~= oldHighY) then setSliderSizeAndPosition() end end local function descendantChanged(this, prop) if internalChange then return end if not this.Visible then return end if prop == "Size" or prop == "Position" then wait() highLowRecheck() end end scrollingFrame.DescendantAdded:connect(function(instance) if not instance:IsA("GuiObject") then return end if instance.Visible then wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end) end) scrollingFrame.DescendantRemoving:connect(function(instance) if not instance:IsA("GuiObject") then return end if descendantsChangeConMap[instance] then descendantsChangeConMap[instance]:disconnect() descendantsChangeConMap[instance] = nil end wait() -- wait a heartbeat for sizes to reconfig highLowRecheck() end) scrollingFrame.Changed:connect(function(prop) if prop == "AbsoluteSize" then if not highY or not lowY then return end highLowRecheck() setSliderSizeAndPosition() end end) return scrollingFrame, controlFrame end t.CreateScrollingFrame = function(orderList,scrollStyle) local frame = Instance.new("Frame") frame.Name = "ScrollingFrame" frame.BackgroundTransparency = 1 frame.Size = UDim2.new(1,0,1,0) local scrollUpButton = Instance.new("ImageButton") scrollUpButton.Name = "ScrollUpButton" scrollUpButton.BackgroundTransparency = 1 scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png" scrollUpButton.Size = UDim2.new(0,17,0,17) local scrollDownButton = Instance.new("ImageButton") scrollDownButton.Name = "ScrollDownButton" scrollDownButton.BackgroundTransparency = 1 scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png" scrollDownButton.Size = UDim2.new(0,17,0,17) local scrollbar = Instance.new("ImageButton") scrollbar.Name = "ScrollBar" scrollbar.Image = "rbxasset://textures/ui/scrollbar.png" scrollbar.BackgroundTransparency = 1 scrollbar.Size = UDim2.new(0, 18, 0, 150) local scrollStamp = 0 local scrollDrag = Instance.new("ImageButton") scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186" scrollDrag.Size = UDim2.new(1, 0, 0, 16) scrollDrag.BackgroundTransparency = 1 scrollDrag.Name = "ScrollDrag" scrollDrag.Active = true scrollDrag.Parent = scrollbar local mouseDrag = Instance.new("ImageButton") mouseDrag.Active = false mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0) mouseDrag.AutoButtonColor = false mouseDrag.BackgroundTransparency = 1 mouseDrag.Name = "mouseDrag" mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0) mouseDrag.ZIndex = 10 local style = "simple" if scrollStyle and tostring(scrollStyle) then style = scrollStyle end local scrollPosition = 1 local rowSize = 0 local howManyDisplayed = 0 local layoutGridScrollBar = function() howManyDisplayed = 0 local guiObjects = {} if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end if scrollPosition < 1 then scrollPosition = 1 end local totalPixelsY = frame.AbsoluteSize.Y local pixelsRemainingY = frame.AbsoluteSize.Y local totalPixelsX = frame.AbsoluteSize.X local xCounter = 0 local rowSizeCounter = 0 local setRowSize = true local pixelsBelowScrollbar = 0 local pos = #guiObjects local currentRowY = 0 pos = scrollPosition --count up from current scroll position to fill out grid while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X --previous pos was the end of a row if xCounter >= totalPixelsX then pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 xCounter = guiObjects[pos].AbsoluteSize.X end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos + 1 end --Count wherever current row left off pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY currentRowY = 0 pos = scrollPosition - 1 xCounter = 0 --objects with varying X,Y dimensions can rarely cause minor errors --rechecking every new scrollPosition is necessary to avoid 100% of errors --count backwards from current scrollPosition to see if we can add more rows while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do xCounter = xCounter + guiObjects[pos].AbsoluteSize.X rowSizeCounter = rowSizeCounter + 1 if xCounter >= totalPixelsX then rowSize = rowSizeCounter - 1 rowSizeCounter = 0 xCounter = guiObjects[pos].AbsoluteSize.X if pixelsBelowScrollbar + currentRowY <= totalPixelsY then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY if scrollPosition <= rowSize then scrollPosition = 1 break else scrollPosition = scrollPosition - rowSize end currentRowY = 0 else break end end if guiObjects[pos].AbsoluteSize.Y > currentRowY then currentRowY = guiObjects[pos].AbsoluteSize.Y end pos = pos - 1 end --Do check last time if pos = 0 if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then scrollPosition = 1 end xCounter = 0 --pos = scrollPosition rowSizeCounter = 0 setRowSize = true local lastChildSize = 0 local xOffset,yOffset = 0 if guiObjects[1] then yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2) xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2) end for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemainingY < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject if setRowSize then rowSizeCounter = rowSizeCounter + 1 end if xCounter + child.AbsoluteSize.X >= totalPixelsX then if setRowSize then rowSize = rowSizeCounter - 1 setRowSize = false end xCounter = 0 pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y end child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset) xCounter = xCounter + child.AbsoluteSize.X child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0) if child.Visible then howManyDisplayed = howManyDisplayed + 1 end lastChildSize = child.AbsoluteSize end end end scrollUpButton.Active = (scrollPosition > 1) if lastChildSize == 0 then scrollDownButton.Active = false else scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0) end scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local layoutSimpleScrollBar = function() local guiObjects = {} howManyDisplayed = 0 if orderList then for i, child in ipairs(orderList) do if child.Parent == frame then table.insert(guiObjects, child) end end else local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then table.insert(guiObjects, child) end end end end if #guiObjects == 0 then scrollUpButton.Active = false scrollDownButton.Active = false scrollDrag.Active = false scrollPosition = 1 return end if scrollPosition > #guiObjects then scrollPosition = #guiObjects end local totalPixels = frame.AbsoluteSize.Y local pixelsRemaining = frame.AbsoluteSize.Y local pixelsBelowScrollbar = 0 local pos = #guiObjects while pixelsBelowScrollbar < totalPixels and pos >= 1 do if pos >= scrollPosition then pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y else if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then --It fits, so back up our scroll position pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y if scrollPosition <= 1 then scrollPosition = 1 break else --local ("Backing up ScrollPosition from -- " ..scrollPosition) scrollPosition = scrollPosition - 1 end else break end end pos = pos - 1 end pos = scrollPosition for i, child in ipairs(guiObjects) do if i < scrollPosition then --print("Hiding " .. child.Name) child.Visible = false else if pixelsRemaining < 0 then --print("Out of Space " .. child.Name) child.Visible = false else --print("Laying out " .. child.Name) --GuiObject child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining) pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y if (pixelsRemaining >= 0) then child.Visible = true howManyDisplayed = howManyDisplayed + 1 else child.Visible = false end end end end scrollUpButton.Active = (scrollPosition > 1) scrollDownButton.Active = (pixelsRemaining < 0) scrollDrag.Active = #guiObjects > howManyDisplayed scrollDrag.Visible = scrollDrag.Active end local moveDragger = function() local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end if not scrollDrag.Parent then return end local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1)) if dragSizeY < 16 then dragSizeY = 16 end scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY) local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed)) if relativeYPos > 1 then relativeYPos = 1 elseif relativeYPos < 0 then relativeYPos = 0 end local absYPos = 0 if relativeYPos ~= 0 then absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y) end scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos) end local reentrancyGuard = false local recalculate = function() if reentrancyGuard then return end reentrancyGuard = true wait() local success, err = nil if style == "grid" then success, err = pcall(function() layoutGridScrollBar() end) elseif style == "simple" then success, err = pcall(function() layoutSimpleScrollBar() end) end if not success then print(err) end moveDragger() reentrancyGuard = false end local doScrollUp = function() scrollPosition = (scrollPosition) - rowSize if scrollPosition < 1 then scrollPosition = 1 end recalculate(nil) end local doScrollDown = function() scrollPosition = (scrollPosition) + rowSize recalculate(nil) end local scrollUp = function(mouseYPos) if scrollUpButton.Active then scrollStamp = tick() local current = scrollStamp local upCon upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil upCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollUp() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollUp() if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then break end if not scrollUpButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local scrollDown = function(mouseYPos) if scrollDownButton.Active then scrollStamp = tick() local current = scrollStamp local downCon downCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil downCon:disconnect() end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) doScrollDown() wait(0.2) local t = tick() local w = 0.1 while scrollStamp == current do doScrollDown() if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then break end if not scrollDownButton.Active then break end if tick()-t > 5 then w = 0 elseif tick()-t > 2 then w = 0.06 end wait(w) end end end local y = 0 scrollDrag.MouseButton1Down:connect(function(x,y) if scrollDrag.Active then scrollStamp = tick() local mouseOffset = y - scrollDrag.AbsolutePosition.y local dragCon local upCon dragCon = mouseDrag.MouseMoved:connect(function(x,y) local barAbsPos = scrollbar.AbsolutePosition.y local barAbsSize = scrollbar.AbsoluteSize.y local dragAbsSize = scrollDrag.AbsoluteSize.y local barAbsOne = barAbsPos + barAbsSize - dragAbsSize y = y - mouseOffset y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y y = y - barAbsPos local guiObjects = 0 local children = frame:GetChildren() if children then for i, child in ipairs(children) do if child:IsA("GuiObject") then guiObjects = guiObjects + 1 end end end local doublePercent = y/(barAbsSize-dragAbsSize) local rowDiff = rowSize local totalScrollCount = guiObjects - (howManyDisplayed - 1) local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff if newScrollPosition < scrollPosition then rowDiff = -rowDiff end if newScrollPosition < 1 then newScrollPosition = 1 end scrollPosition = newScrollPosition recalculate(nil) end) upCon = mouseDrag.MouseButton1Up:connect(function() scrollStamp = tick() mouseDrag.Parent = nil dragCon:disconnect(); dragCon = nil upCon:disconnect(); drag = nil end) mouseDrag.Parent = getScreenGuiAncestor(scrollbar) end end) local scrollMouseCount = 0 scrollUpButton.MouseButton1Down:connect( function() scrollUp() end) scrollUpButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollDownButton.MouseButton1Down:connect( function() scrollDown() end) scrollbar.MouseButton1Up:connect(function() scrollStamp = tick() end) scrollbar.MouseButton1Down:connect( function(x,y) if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then scrollDown(y) elseif y < (scrollDrag.AbsolutePosition.y) then scrollUp(y) end end) frame.ChildAdded:connect(function() recalculate(nil) end) frame.ChildRemoved:connect(function() recalculate(nil) end) frame.Changed:connect( function(prop) if prop == "AbsoluteSize" then --Wait a heartbeat for it to sync in recalculate(nil) end end) frame.AncestryChanged:connect(function() recalculate(nil) end) return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar end local function binaryGrow(min, max, fits) if min > max then return min end local biggestLegal = min while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then biggestLegal = mid --Try growing min = mid + 1 else --Doesn't fit, shrink max = mid - 1 end end return biggestLegal end local function binaryShrink(min, max, fits) if min > max then return min end local smallestLegal = max while min <= max do local mid = min + math.floor((max - min) / 2) if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then smallestLegal = mid --It fits, shrink max = mid - 1 else --Doesn't fit, grow min = mid + 1 end end return smallestLegal end local function getGuiOwner(instance) while instance ~= nil do if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then return instance end instance = instance.Parent end return nil end t.AutoTruncateTextObject = function(textLabel) local text = textLabel.Text local fullLabel = textLabel:Clone() fullLabel.Name = "Full" .. textLabel.Name fullLabel.BorderSizePixel = 0 fullLabel.BackgroundTransparency = 0 fullLabel.Text = text fullLabel.TextXAlignment = Enum.TextXAlignment.Center fullLabel.Position = UDim2.new(0,-3,0,0) fullLabel.Size = UDim2.new(0,100,1,0) fullLabel.Visible = false fullLabel.Parent = textLabel local shortText = nil local mouseEnterConnection = nil local mouseLeaveConnection= nil local checkForResize = function() if getGuiOwner(textLabel) == nil then return end textLabel.Text = text if textLabel.TextFits then --Tear down the rollover if it is active if mouseEnterConnection then mouseEnterConnection:disconnect() mouseEnterConnection = nil end if mouseLeaveConnection then mouseLeaveConnection:disconnect() mouseLeaveConnection = nil end else local len = string.len(text) textLabel.Text = text .. "~" --Shrink the text local textSize = binaryGrow(0, len, function(pos) if pos == 0 then textLabel.Text = "~" else textLabel.Text = string.sub(text, 1, pos) .. "~" end return textLabel.TextFits end) shortText = string.sub(text, 1, textSize) .. "~" textLabel.Text = shortText --Make sure the fullLabel fits if not fullLabel.TextFits then --Already too small, grow it really bit to start fullLabel.Size = UDim2.new(0, 10000, 1, 0) end --Okay, now try to binary shrink it back down local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X, function(size) fullLabel.Size = UDim2.new(0, size, 1, 0) return fullLabel.TextFits end) fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0) --Now setup the rollover effects, if they are currently off if mouseEnterConnection == nil then mouseEnterConnection = textLabel.MouseEnter:connect( function() fullLabel.ZIndex = textLabel.ZIndex + 1 fullLabel.Visible = true --textLabel.Text = "" end) end if mouseLeaveConnection == nil then mouseLeaveConnection = textLabel.MouseLeave:connect( function() fullLabel.Visible = false --textLabel.Text = shortText end) end end end textLabel.AncestryChanged:connect(checkForResize) textLabel.Changed:connect( function(prop) if prop == "AbsoluteSize" then checkForResize() end end) checkForResize() local function changeText(newText) text = newText fullLabel.Text = text checkForResize() end return textLabel, changeText end local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue) if fromPage then fromPage.Visible = false if transitionFrame.Visible == false then transitionFrame.Size = fromPage.Size transitionFrame.Position = fromPage.Position end else if transitionFrame.Visible == false then transitionFrame.Size = UDim2.new(0.0,50,0.0,50) transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25) end end transitionFrame.Visible = true currentPageValue.Value = nil local newsize, newPosition if toPage then --Make it visible so it resizes toPage.Visible = true newSize = toPage.Size newPosition = toPage.Position toPage.Visible = false else newSize = UDim2.new(0.0,50,0.0,50) newPosition = UDim2.new(0.5,-25,0.5,-25) end transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true, function(state) if state == Enum.TweenStatus.Completed then transitionFrame.Visible = false if toPage then toPage.Visible = true currentPageValue.Value = toPage end end end) end t.CreateTutorial = function(name, tutorialKey, createButtons) local frame = Instance.new("Frame") frame.Name = "Tutorial-" .. name frame.BackgroundTransparency = 1 frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) local transitionFrame = Instance.new("Frame") transitionFrame.Name = "TransitionFrame" transitionFrame.Style = Enum.FrameStyle.RobloxRound transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0) transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0) transitionFrame.Visible = false transitionFrame.Parent = frame local currentPageValue = Instance.new("ObjectValue") currentPageValue.Name = "CurrentTutorialPage" currentPageValue.Value = nil currentPageValue.Parent = frame local boolValue = Instance.new("BoolValue") boolValue.Name = "Buttons" boolValue.Value = createButtons boolValue.Parent = frame local pages = Instance.new("Frame") pages.Name = "Pages" pages.BackgroundTransparency = 1 pages.Size = UDim2.new(1,0,1,0) pages.Parent = frame local function getVisiblePageAndHideOthers() local visiblePage = nil local children = pages:GetChildren() if children then for i,child in ipairs(children) do if child.Visible then if visiblePage then child.Visible = false else visiblePage = child end end end end return visiblePage end local showTutorial = function(alwaysShow) if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then print("Showing tutorial-",tutorialKey) local currentTutorialPage = getVisiblePageAndHideOthers() local firstPage = pages:FindFirstChild("TutorialPage1") if firstPage then TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue) else error("Could not find TutorialPage1") end end end local dismissTutorial = function() local currentTutorialPage = getVisiblePageAndHideOthers() if currentTutorialPage then TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue) end UserSettings().GameSettings:SetTutorialState(tutorialKey, true) end local gotoPage = function(pageNum) local page = pages:FindFirstChild("TutorialPage" .. pageNum) local currentTutorialPage = getVisiblePageAndHideOthers() TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue) end return frame, showTutorial, dismissTutorial, gotoPage end local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton) local frame = Instance.new("Frame") frame.Name = "TutorialPage" frame.Style = Enum.FrameStyle.RobloxRound frame.Size = UDim2.new(0.6, 0, 0.6, 0) frame.Position = UDim2.new(0.2, 0, 0.2, 0) frame.Visible = false local frameHeader = Instance.new("TextLabel") frameHeader.Name = "Header" frameHeader.Text = name frameHeader.BackgroundTransparency = 1 frameHeader.FontSize = Enum.FontSize.Size24 frameHeader.Font = Enum.Font.ArialBold frameHeader.TextColor3 = Color3.new(1,1,1) frameHeader.TextXAlignment = Enum.TextXAlignment.Center frameHeader.TextWrap = true frameHeader.Size = UDim2.new(1,-55, 0, 22) frameHeader.Position = UDim2.new(0,0,0,0) frameHeader.Parent = frame local skipButton = Instance.new("ImageButton") skipButton.Name = "SkipButton" skipButton.AutoButtonColor = false skipButton.BackgroundTransparency = 1 skipButton.Image = "rbxasset://textures/ui/closeButton.png" skipButton.MouseButton1Click:connect(function() skipTutorial() end) skipButton.MouseEnter:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png" end) skipButton.MouseLeave:connect(function() skipButton.Image = "rbxasset://textures/ui/closeButton.png" end) skipButton.Size = UDim2.new(0, 25, 0, 25) skipButton.Position = UDim2.new(1, -25, 0, 0) skipButton.Parent = frame if giveDoneButton then local doneButton = Instance.new("TextButton") doneButton.Name = "DoneButton" doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault doneButton.Text = "Done" doneButton.TextColor3 = Color3.new(1,1,1) doneButton.Font = Enum.Font.ArialBold doneButton.FontSize = Enum.FontSize.Size18 doneButton.Size = UDim2.new(0,100,0,50) doneButton.Position = UDim2.new(0.5,-50,1,-50) if skipTutorial then doneButton.MouseButton1Click:connect(function() skipTutorial() end) end doneButton.Parent = frame end local innerFrame = Instance.new("Frame") innerFrame.Name = "ContentFrame" innerFrame.BackgroundTransparency = 1 innerFrame.Position = UDim2.new(0,0,0,25) innerFrame.Parent = frame local nextButton = Instance.new("TextButton") nextButton.Name = "NextButton" nextButton.Text = "Next" nextButton.TextColor3 = Color3.new(1,1,1) nextButton.Font = Enum.Font.Arial nextButton.FontSize = Enum.FontSize.Size18 nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault nextButton.Size = UDim2.new(0,80, 0, 32) nextButton.Position = UDim2.new(0.5, 5, 1, -32) nextButton.Active = false nextButton.Visible = false nextButton.Parent = frame local prevButton = Instance.new("TextButton") prevButton.Name = "PrevButton" prevButton.Text = "Previous" prevButton.TextColor3 = Color3.new(1,1,1) prevButton.Font = Enum.Font.Arial prevButton.FontSize = Enum.FontSize.Size18 prevButton.Style = Enum.ButtonStyle.RobloxButton prevButton.Size = UDim2.new(0,80, 0, 32) prevButton.Position = UDim2.new(0.5, -85, 1, -32) prevButton.Active = false prevButton.Visible = false prevButton.Parent = frame if giveDoneButton then innerFrame.Size = UDim2.new(1,0,1,-75) else innerFrame.Size = UDim2.new(1,0,1,-22) end local parentConnection = nil local function basicHandleResize() if frame.Visible and frame.Parent then local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y) handleResize(200,maxSize) end end frame.Changed:connect( function(prop) if prop == "Parent" then if parentConnection ~= nil then parentConnection:disconnect() parentConnection = nil end if frame.Parent and frame.Parent:IsA("GuiObject") then parentConnection = frame.Parent.Changed:connect( function(parentProp) if parentProp == "AbsoluteSize" then wait() basicHandleResize() end end) basicHandleResize() end end if prop == "Visible" then basicHandleResize() end end) return frame, innerFrame end t.CreateTextTutorialPage = function(name, text, skipTutorialFunc) local frame = nil local contentFrame = nil local textLabel = Instance.new("TextLabel") textLabel.BackgroundTransparency = 1 textLabel.TextColor3 = Color3.new(1,1,1) textLabel.Text = text textLabel.TextWrap = true textLabel.TextXAlignment = Enum.TextXAlignment.Left textLabel.TextYAlignment = Enum.TextYAlignment.Center textLabel.Font = Enum.Font.Arial textLabel.FontSize = Enum.FontSize.Size14 textLabel.Size = UDim2.new(1,0,1,0) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) frame.Size = UDim2.new(0, size, 0, size) return textLabel.TextFits end) frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc) textLabel.Parent = contentFrame return frame end t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton) local frame = nil local contentFrame = nil local imageLabel = Instance.new("ImageLabel") imageLabel.BackgroundTransparency = 1 imageLabel.Image = imageAsset imageLabel.Size = UDim2.new(0,x,0,y) imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2) local function handleResize(minSize, maxSize) size = binaryShrink(minSize, maxSize, function(size) return size >= x and size >= y end) if size >= x and size >= y then imageLabel.Size = UDim2.new(0,x, 0,y) imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2) else if x > y then --X is limiter, so imageLabel.Size = UDim2.new(1,0,y/x,0) imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0) else --Y is limiter imageLabel.Size = UDim2.new(x/y,0,1, 0) imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0) end end size = size + 50 frame.Size = UDim2.new(0, size, 0, size) frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2) end frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton) imageLabel.Parent = contentFrame return frame end t.AddTutorialPage = function(tutorial, tutorialPage) local transitionFrame = tutorial.TransitionFrame local currentPageValue = tutorial.CurrentTutorialPage if not tutorial.Buttons.Value then tutorialPage.NextButton.Parent = nil tutorialPage.PrevButton.Parent = nil end local children = tutorial.Pages:GetChildren() if children and #children > 0 then tutorialPage.Name = "TutorialPage" .. (#children+1) local previousPage = children[#children] if not previousPage:IsA("GuiObject") then error("All elements under Pages must be GuiObjects") end if tutorial.Buttons.Value then if previousPage.NextButton.Active then error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function") end previousPage.NextButton.MouseButton1Click:connect( function() TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue) end) previousPage.NextButton.Active = true previousPage.NextButton.Visible = true if tutorialPage.PrevButton.Active then error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function") end tutorialPage.PrevButton.MouseButton1Click:connect( function() TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue) end) tutorialPage.PrevButton.Active = true tutorialPage.PrevButton.Visible = true end tutorialPage.Parent = tutorial.Pages else --First child tutorialPage.Name = "TutorialPage1" tutorialPage.Parent = tutorial.Pages end end t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId) if not userIdsForSets then error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids") end if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata") end if not objectSelected then error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!") end if type(objectSelected) ~= "function" then error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!") end if dialogClosed and type(dialogClosed) ~= "function" then error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!") end if showAdminCategories == nil then -- by default, don't show beta sets showAdminCategories = false end local arrayPosition = 1 local insertButtons = {} local insertButtonCons = {} local contents = nil local setGui = nil -- used for water selections local waterForceDirection = "NegX" local waterForce = "None" local waterGui, waterTypeChangedEvent = nil local Data = {} Data.CurrentCategory = nil Data.Category = {} local SetCache = {} local userCategoryButtons = nil local buttonWidth = 64 local buttonHeight = buttonWidth local SmallThumbnailUrl = nil local LargeThumbnailUrl = nil local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower() if useAssetVersionId then LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid=" else LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid=" SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid=" end local function drillDownSetZIndex(parent, index) local children = parent:GetChildren() for i = 1, #children do if children[i]:IsA("GuiObject") then children[i].ZIndex = index end drillDownSetZIndex(children[i], index) end end -- for terrain stamping local currTerrainDropDownFrame = nil local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"} local terrainShapeMap = {} for i = 1, #terrainShapes do terrainShapeMap[terrainShapes[i]] = i - 1 end terrainShapeMap[terrainShapes[#terrainShapes]] = 6 local function createWaterGui() local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"} local waterForces = {"None", "Small", "Medium", "Strong", "Max"} local waterFrame = Instance.new("Frame") waterFrame.Name = "WaterFrame" waterFrame.Style = Enum.FrameStyle.RobloxSquare waterFrame.Size = UDim2.new(0,150,0,110) waterFrame.Visible = false local waterForceLabel = Instance.new("TextLabel") waterForceLabel.Name = "WaterForceLabel" waterForceLabel.BackgroundTransparency = 1 waterForceLabel.Size = UDim2.new(1,0,0,12) waterForceLabel.Font = Enum.Font.ArialBold waterForceLabel.FontSize = Enum.FontSize.Size12 waterForceLabel.TextColor3 = Color3.new(1,1,1) waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left waterForceLabel.Text = "Water Force" waterForceLabel.Parent = waterFrame local waterForceDirLabel = waterForceLabel:Clone() waterForceDirLabel.Name = "WaterForceDirectionLabel" waterForceDirLabel.Text = "Water Force Direction" waterForceDirLabel.Position = UDim2.new(0,0,0,50) waterForceDirLabel.Parent = waterFrame local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame) waterTypeChangedEvent.Name = "WaterTypeChangedEvent" local waterForceDirectionSelectedFunc = function(newForceDirection) waterForceDirection = newForceDirection waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceSelectedFunc = function(newForce) waterForce = newForce waterTypeChangedEvent:Fire({waterForce, waterForceDirection}) end local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc) waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25) waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3) forceWaterDirectionSelection("NegX") waterForceDirectionDropDown.Parent = waterForceDirLabel local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc) forceWaterForceSelection("None") waterForceDropDown.Size = UDim2.new(1,0,0,25) waterForceDropDown.Position = UDim2.new(0,0,1,3) waterForceDropDown.Parent = waterForceLabel return waterFrame, waterTypeChangedEvent end -- Helper Function that contructs gui elements local function createSetGui() local setGui = Instance.new("ScreenGui") setGui.Name = "SetGui" local setPanel = Instance.new("Frame") setPanel.Name = "SetPanel" setPanel.Active = true setPanel.BackgroundTransparency = 1 if position then setPanel.Position = position else setPanel.Position = UDim2.new(0.2, 29, 0.1, 24) end if size then setPanel.Size = size else setPanel.Size = UDim2.new(0.6, -58, 0.64, 0) end setPanel.Style = Enum.FrameStyle.RobloxRound setPanel.ZIndex = 6 setPanel.Parent = setGui -- Children of SetPanel local itemPreview = Instance.new("Frame") itemPreview.Name = "ItemPreview" itemPreview.BackgroundTransparency = 1 itemPreview.Position = UDim2.new(0.8,5,0.085,0) itemPreview.Size = UDim2.new(0.21,0,0.9,0) itemPreview.ZIndex = 6 itemPreview.Parent = setPanel -- Children of ItemPreview local textPanel = Instance.new("Frame") textPanel.Name = "TextPanel" textPanel.BackgroundTransparency = 1 textPanel.Position = UDim2.new(0,0,0.45,0) textPanel.Size = UDim2.new(1,0,0.55,0) textPanel.ZIndex = 6 textPanel.Parent = itemPreview -- Children of TextPanel local rolloverText = Instance.new("TextLabel") rolloverText.Name = "RolloverText" rolloverText.BackgroundTransparency = 1 rolloverText.Size = UDim2.new(1,0,0,48) rolloverText.ZIndex = 6 rolloverText.Font = Enum.Font.ArialBold rolloverText.FontSize = Enum.FontSize.Size24 rolloverText.Text = "" rolloverText.TextColor3 = Color3.new(1,1,1) rolloverText.TextWrap = true rolloverText.TextXAlignment = Enum.TextXAlignment.Left rolloverText.TextYAlignment = Enum.TextYAlignment.Top rolloverText.Parent = textPanel local largePreview = Instance.new("ImageLabel") largePreview.Name = "LargePreview" largePreview.BackgroundTransparency = 1 largePreview.Image = "" largePreview.Size = UDim2.new(1,0,0,170) largePreview.ZIndex = 6 largePreview.Parent = itemPreview local sets = Instance.new("Frame") sets.Name = "Sets" sets.BackgroundTransparency = 1 sets.Position = UDim2.new(0,0,0,5) sets.Size = UDim2.new(0.23,0,1,-5) sets.ZIndex = 6 sets.Parent = setPanel -- Children of Sets local line = Instance.new("Frame") line.Name = "Line" line.BackgroundColor3 = Color3.new(1,1,1) line.BackgroundTransparency = 0.7 line.BorderSizePixel = 0 line.Position = UDim2.new(1,-3,0.06,0) line.Size = UDim2.new(0,3,0.9,0) line.ZIndex = 6 line.Parent = sets local setsLists, controlFrame = t.CreateTrueScrollingFrame() setsLists.Size = UDim2.new(1,-6,0.94,0) setsLists.Position = UDim2.new(0,0,0.06,0) setsLists.BackgroundTransparency = 1 setsLists.Name = "SetsLists" setsLists.ZIndex = 6 setsLists.Parent = sets drillDownSetZIndex(controlFrame, 7) local setsHeader = Instance.new("TextLabel") setsHeader.Name = "SetsHeader" setsHeader.BackgroundTransparency = 1 setsHeader.Size = UDim2.new(0,47,0,24) setsHeader.ZIndex = 6 setsHeader.Font = Enum.Font.ArialBold setsHeader.FontSize = Enum.FontSize.Size24 setsHeader.Text = "Sets" setsHeader.TextColor3 = Color3.new(1,1,1) setsHeader.TextXAlignment = Enum.TextXAlignment.Left setsHeader.TextYAlignment = Enum.TextYAlignment.Top setsHeader.Parent = sets local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(1,-32,0,-2) cancelButton.Size = UDim2.new(0,34,0,34) cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault cancelButton.ZIndex = 6 cancelButton.Text = "" cancelButton.Modal = true cancelButton.Parent = setPanel -- Children of Cancel Button local cancelImage = Instance.new("ImageLabel") cancelImage.Name = "CancelImage" cancelImage.BackgroundTransparency = 1 cancelImage.Image = "http://www.roblox.com/asset/?id=54135717" cancelImage.Position = UDim2.new(0,-2,0,-2) cancelImage.Size = UDim2.new(0,16,0,16) cancelImage.ZIndex = 6 cancelImage.Parent = cancelButton return setGui end local function createSetButton(text) local setButton = Instance.new("TextButton") if text then setButton.Text = text else setButton.Text = "" end setButton.AutoButtonColor = false setButton.BackgroundTransparency = 1 setButton.BackgroundColor3 = Color3.new(1,1,1) setButton.BorderSizePixel = 0 setButton.Size = UDim2.new(1,-5,0,18) setButton.ZIndex = 6 setButton.Visible = false setButton.Font = Enum.Font.Arial setButton.FontSize = Enum.FontSize.Size18 setButton.TextColor3 = Color3.new(1,1,1) setButton.TextXAlignment = Enum.TextXAlignment.Left return setButton end local function buildSetButton(name, setId, setImageId, i, count) local button = createSetButton(name) button.Text = name button.Name = "SetButton" button.Visible = true local setValue = Instance.new("IntValue") setValue.Name = "SetId" setValue.Value = setId setValue.Parent = button local setName = Instance.new("StringValue") setName.Name = "SetName" setName.Value = name setName.Parent = button return button end local function processCategory(sets) local setButtons = {} local numSkipped = 0 for i = 1, #sets do if not showAdminCategories and sets[i].Name == "Beta" then numSkipped = numSkipped + 1 else setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets) end end return setButtons end local function handleResize() wait() -- neccessary to insure heartbeat happened local itemPreview = setGui.SetPanel.ItemPreview itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X) itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0) itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y) itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y) end local function makeInsertAssetButton() local insertAssetButtonExample = Instance.new("Frame") insertAssetButtonExample.Name = "InsertAssetButtonExample" insertAssetButtonExample.Position = UDim2.new(0,128,0,64) insertAssetButtonExample.Size = UDim2.new(0,64,0,64) insertAssetButtonExample.BackgroundTransparency = 1 insertAssetButtonExample.ZIndex = 6 insertAssetButtonExample.Visible = false local assetId = Instance.new("IntValue") assetId.Name = "AssetId" assetId.Value = 0 assetId.Parent = insertAssetButtonExample local assetName = Instance.new("StringValue") assetName.Name = "AssetName" assetName.Value = "" assetName.Parent = insertAssetButtonExample local button = Instance.new("TextButton") button.Name = "Button" button.Text = "" button.Style = Enum.ButtonStyle.RobloxButton button.Position = UDim2.new(0.025,0,0.025,0) button.Size = UDim2.new(0.95,0,0.95,0) button.ZIndex = 6 button.Parent = insertAssetButtonExample local buttonImage = Instance.new("ImageLabel") buttonImage.Name = "ButtonImage" buttonImage.Image = "" buttonImage.Position = UDim2.new(0,-7,0,-7) buttonImage.Size = UDim2.new(1,14,1,14) buttonImage.BackgroundTransparency = 1 buttonImage.ZIndex = 7 buttonImage.Parent = button local configIcon = buttonImage:clone() configIcon.Name = "ConfigIcon" configIcon.Visible = false configIcon.Position = UDim2.new(1,-23,1,-24) configIcon.Size = UDim2.new(0,16,0,16) configIcon.Image = "" configIcon.ZIndex = 6 configIcon.Parent = insertAssetButtonExample return insertAssetButtonExample end local function showLargePreview(insertButton) if insertButton:FindFirstChild("AssetId") then delay(0,function() game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)) setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value) end) end if insertButton:FindFirstChild("AssetName") then setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value end end local function selectTerrainShape(shape) if currTerrainDropDownFrame then objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape) end end local function createTerrainTypeButton(name, parent) local dropDownTextButton = Instance.new("TextButton") dropDownTextButton.Name = name .. "Button" dropDownTextButton.Font = Enum.Font.ArialBold dropDownTextButton.FontSize = Enum.FontSize.Size14 dropDownTextButton.BorderSizePixel = 0 dropDownTextButton.TextColor3 = Color3.new(1,1,1) dropDownTextButton.Text = name dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.ZIndex = parent.ZIndex + 1 dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16) dropDownTextButton.Position = UDim2.new(0,1,0,0) dropDownTextButton.MouseEnter:connect(function() dropDownTextButton.BackgroundTransparency = 0 dropDownTextButton.TextColor3 = Color3.new(0,0,0) end) dropDownTextButton.MouseLeave:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) end) dropDownTextButton.MouseButton1Click:connect(function() dropDownTextButton.BackgroundTransparency = 1 dropDownTextButton.TextColor3 = Color3.new(1,1,1) if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then dropDownTextButton.Parent.Visible = false end selectTerrainShape(terrainShapeMap[dropDownTextButton.Text]) end) return dropDownTextButton end local function createTerrainDropDownMenu(zIndex) local dropDown = Instance.new("Frame") dropDown.Name = "TerrainDropDown" dropDown.BackgroundColor3 = Color3.new(0,0,0) dropDown.BorderColor3 = Color3.new(1,0,0) dropDown.Size = UDim2.new(0,200,0,0) dropDown.Visible = false dropDown.ZIndex = zIndex dropDown.Parent = setGui for i = 1, #terrainShapes do local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown) shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset)) shapeButton.Parent = dropDown dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset)) end dropDown.MouseLeave:connect(function() dropDown.Visible = false end) end local function createDropDownMenuButton(parent) local dropDownButton = Instance.new("ImageButton") dropDownButton.Name = "DropDownButton" dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509" dropDownButton.BackgroundTransparency = 1 dropDownButton.Size = UDim2.new(0,16,0,16) dropDownButton.Position = UDim2.new(1,-24,0,6) dropDownButton.ZIndex = parent.ZIndex + 2 dropDownButton.Parent = parent if not setGui:FindFirstChild("TerrainDropDown") then createTerrainDropDownMenu(8) end dropDownButton.MouseButton1Click:connect(function() setGui.TerrainDropDown.Visible = true setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y) currTerrainDropDownFrame = parent end) end local function buildInsertButton() local insertButton = makeInsertAssetButton() insertButton.Name = "InsertAssetButton" insertButton.Visible = true if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then createDropDownMenuButton(insertButton) end local lastEnter = nil local mouseEnterCon = insertButton.MouseEnter:connect(function() lastEnter = insertButton delay(0.1,function() if lastEnter == insertButton then showLargePreview(insertButton) end end) end) return insertButton, mouseEnterCon end local function realignButtonGrid(columns) local x = 0 local y = 0 for i = 1, #insertButtons do insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y) x = x + 1 if x >= columns then x = 0 y = y + 1 end end end local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId) if visible then insertFrame.AssetName.Value = name insertFrame.AssetId.Value = assetId local newImageUrl = SmallThumbnailUrl .. assetId if newImageUrl ~= insertFrame.Button.ButtonImage.Image then delay(0,function() game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId) if insertFrame:findFirstChild("Button") then insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId end end) end table.insert(insertButtonCons, insertFrame.Button.MouseButton1Click:connect(function() -- special case for water, show water selection gui local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability") waterGui.Visible = isWaterSelected if isWaterSelected then objectSelected(name, tonumber(assetId), nil) else objectSelected(name, tonumber(assetId)) end end) ) insertFrame.Visible = true else insertFrame.Visible = false end end local function loadSectionOfItems(setGui, rows, columns) local pageSize = rows * columns if arrayPosition > #contents then return end local origArrayPos = arrayPosition local yCopy = 0 for i = 1, pageSize + 1 do if arrayPosition >= #contents + 1 then break end local buttonCon insertButtons[arrayPosition], buttonCon = buildInsertButton() table.insert(insertButtonCons,buttonCon) insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame arrayPosition = arrayPosition + 1 end realignButtonGrid(columns) local indexCopy = origArrayPos for index = origArrayPos, arrayPosition do if insertButtons[index] then if contents[index] then -- we don't want water to have a drop down button if contents[index].Name == "Water" then if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy() end end local assetId if useAssetVersionId then assetId = contents[index].AssetVersionId else assetId = contents[index].AssetId end setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId) else break end else break end indexCopy = index end end local function setSetIndex() Data.Category[Data.CurrentCategory].Index = 0 rows = 7 columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) contents = Data.Category[Data.CurrentCategory].Contents if contents then -- remove our buttons and their connections for i = 1, #insertButtons do insertButtons[i]:remove() end for i = 1, #insertButtonCons do if insertButtonCons[i] then insertButtonCons[i]:disconnect() end end insertButtonCons = {} insertButtons = {} arrayPosition = 1 loadSectionOfItems(setGui, rows, columns) end end local function selectSet(button, setName, setId, setIndex) if button and Data.Category[Data.CurrentCategory] ~= nil then if button ~= Data.Category[Data.CurrentCategory].Button then Data.Category[Data.CurrentCategory].Button = button if SetCache[setId] == nil then SetCache[setId] = game:GetService("InsertService"):GetCollection(setId) end Data.Category[Data.CurrentCategory].Contents = SetCache[setId] Data.Category[Data.CurrentCategory].SetName = setName Data.Category[Data.CurrentCategory].SetId = setId end setSetIndex() end end local function selectCategoryPage(buttons, page) if buttons ~= Data.CurrentCategory then if Data.CurrentCategory then for key, button in pairs(Data.CurrentCategory) do button.Visible = false end end Data.CurrentCategory = buttons if Data.Category[Data.CurrentCategory] == nil then Data.Category[Data.CurrentCategory] = {} if #buttons > 0 then selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0) end else Data.Category[Data.CurrentCategory].Button = nil selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index) end end end local function selectCategory(category) selectCategoryPage(category, 0) end local function resetAllSetButtonSelection() local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren() for i = 1, #setButtons do if setButtons[i]:IsA("TextButton") then setButtons[i].Selected = false setButtons[i].BackgroundTransparency = 1 setButtons[i].TextColor3 = Color3.new(1,1,1) setButtons[i].BackgroundColor3 = Color3.new(1,1,1) end end end local function populateSetsFrame() local currRow = 0 for i = 1, #userCategoryButtons do local button = userCategoryButtons[i] button.Visible = true button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset) button.Parent = setGui.SetPanel.Sets.SetsLists if i == 1 then -- we will have this selected by default, so show it button.Selected = true button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 end button.MouseEnter:connect(function() if not button.Selected then button.BackgroundTransparency = 0 button.TextColor3 = Color3.new(0,0,0) end end) button.MouseLeave:connect(function() if not button.Selected then button.BackgroundTransparency = 1 button.TextColor3 = Color3.new(1,1,1) end end) button.MouseButton1Click:connect(function() resetAllSetButtonSelection() button.Selected = not button.Selected button.BackgroundColor3 = Color3.new(0,204/255,0) button.TextColor3 = Color3.new(0,0,0) button.BackgroundTransparency = 0 selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0) end) currRow = currRow + 1 end local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren() -- set first category as loaded for default if buttons then for i = 1, #buttons do if buttons[i]:IsA("TextButton") then selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0) selectCategory(userCategoryButtons) break end end end end setGui = createSetGui() waterGui, waterTypeChangedEvent = createWaterGui() waterGui.Position = UDim2.new(0,55,0,0) waterGui.Parent = setGui setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size if prop == "AbsoluteSize" then handleResize() setSetIndex() end end) local scrollFrame, controlFrame = t.CreateTrueScrollingFrame() scrollFrame.Size = UDim2.new(0.54,0,0.85,0) scrollFrame.Position = UDim2.new(0.24,0,0.085,0) scrollFrame.Name = "ItemsFrame" scrollFrame.ZIndex = 6 scrollFrame.Parent = setGui.SetPanel scrollFrame.BackgroundTransparency = 1 drillDownSetZIndex(controlFrame,7) controlFrame.Parent = setGui.SetPanel controlFrame.Position = UDim2.new(0.76, 5, 0, 0) local debounce = false controlFrame.ScrollBottom.Changed:connect(function(prop) if controlFrame.ScrollBottom.Value == true then if debounce then return end debounce = true loadSectionOfItems(setGui, rows, columns) debounce = false end end) local userData = {} for id = 1, #userIdsForSets do local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id]) if newUserData and #newUserData > 2 then -- start at #3 to skip over My Decals and My Models for each account for category = 3, #newUserData do if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first table.insert(userData,1,newUserData[category]) else table.insert(userData, newUserData[category]) end end end end if userData then userCategoryButtons = processCategory(userData) end rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight) columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth) populateSetsFrame() insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function() setGui.SetPanel.Visible = false if dialogClosed then dialogClosed() end end) local setVisibilityFunction = function(visible) if visible then setGui.SetPanel.Visible = true else setGui.SetPanel.Visible = false end end local getVisibilityFunction = function() if setGui then if setGui:FindFirstChild("SetPanel") then return setGui.SetPanel.Visible end end return false end return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent end t.CreateTerrainMaterialSelector = function(size,position) local terrainMaterialSelectionChanged = Instance.new("BindableEvent") terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged" local selectedButton = nil local frame = Instance.new("Frame") frame.Name = "TerrainMaterialSelector" if size then frame.Size = size else frame.Size = UDim2.new(0, 245, 0, 230) end if position then frame.Position = position end frame.BorderSizePixel = 0 frame.BackgroundColor3 = Color3.new(0,0,0) frame.Active = true terrainMaterialSelectionChanged.Parent = frame local waterEnabled = true -- todo: turn this on when water is ready local materialToImageMap = {} local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"} if waterEnabled then table.insert(materialNames,"Water") end local currentMaterial = 1 function getEnumFromName(choice) if choice == "Grass" then return 1 end if choice == "Sand" then return 2 end if choice == "Erase" then return 0 end if choice == "Brick" then return 3 end if choice == "Granite" then return 4 end if choice == "Asphalt" then return 5 end if choice == "Iron" then return 6 end if choice == "Aluminum" then return 7 end if choice == "Gold" then return 8 end if choice == "Plank" then return 9 end if choice == "Log" then return 10 end if choice == "Gravel" then return 11 end if choice == "Cinder Block" then return 12 end if choice == "Stone Wall" then return 13 end if choice == "Concrete" then return 14 end if choice == "Plastic (red)" then return 15 end if choice == "Plastic (blue)" then return 16 end if choice == "Water" then return 17 end end function getNameFromEnum(choice) if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end if waterEnabled then if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end end end local function updateMaterialChoice(choice) currentMaterial = getEnumFromName(choice) terrainMaterialSelectionChanged:Fire(currentMaterial) end -- we so need a better way to do this for i,v in pairs(materialNames) do materialToImageMap[v] = {} if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112" elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652" elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537" elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153" elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038" elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093" elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995" elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118" elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848" elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924" elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015" elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051" elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206" elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103" elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804" elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059" elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474" else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!! end end local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid") scrollFrame.Size = UDim2.new(0.85,0,1,0) scrollFrame.Position = UDim2.new(0,0,0,0) scrollFrame.Parent = frame scrollUp.Parent = frame scrollUp.Visible = true scrollUp.Position = UDim2.new(1,-19,0,0) scrollDown.Parent = frame scrollDown.Visible = true scrollDown.Position = UDim2.new(1,-19,1,-17) local function goToNewMaterial(buttonWrap, materialName) updateMaterialChoice(materialName) buttonWrap.BackgroundTransparency = 0 selectedButton.BackgroundTransparency = 1 selectedButton = buttonWrap end local function createMaterialButton(name) local buttonWrap = Instance.new("TextButton") buttonWrap.Text = "" buttonWrap.Size = UDim2.new(0,32,0,32) buttonWrap.BackgroundColor3 = Color3.new(1,1,1) buttonWrap.BorderSizePixel = 0 buttonWrap.BackgroundTransparency = 1 buttonWrap.AutoButtonColor = false buttonWrap.Name = tostring(name) local imageButton = Instance.new("ImageButton") imageButton.AutoButtonColor = false imageButton.BackgroundTransparency = 1 imageButton.Size = UDim2.new(0,30,0,30) imageButton.Position = UDim2.new(0,1,0,1) imageButton.Name = tostring(name) imageButton.Parent = buttonWrap imageButton.Image = materialToImageMap[name].Regular local enumType = Instance.new("NumberValue") enumType.Name = "EnumType" enumType.Parent = buttonWrap enumType.Value = 0 imageButton.MouseEnter:connect(function() buttonWrap.BackgroundTransparency = 0 end) imageButton.MouseLeave:connect(function() if selectedButton ~= buttonWrap then buttonWrap.BackgroundTransparency = 1 end end) imageButton.MouseButton1Click:connect(function() if selectedButton ~= buttonWrap then goToNewMaterial(buttonWrap, tostring(name)) end end) return buttonWrap end for i = 1, #materialNames do local imageButton = createMaterialButton(materialNames[i]) if materialNames[i] == "Grass" then -- always start with grass as the default selectedButton = imageButton imageButton.BackgroundTransparency = 0 end imageButton.Parent = scrollFrame end local forceTerrainMaterialSelection = function(newMaterialType) if not newMaterialType then return end if currentMaterial == newMaterialType then return end local matName = getNameFromEnum(newMaterialType) local buttons = scrollFrame:GetChildren() for i = 1, #buttons do if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end if string.find(buttons[i].Name, matName) then goToNewMaterial(buttons[i],matName) return end end end frame.Changed:connect(function ( prop ) if prop == "AbsoluteSize" then recalculateScroll() end end) recalculateScroll() return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection end t.CreateLoadingFrame = function(name,size,position) game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053") local loadingFrame = Instance.new("Frame") loadingFrame.Name = "LoadingFrame" loadingFrame.Style = Enum.FrameStyle.RobloxRound if size then loadingFrame.Size = size else loadingFrame.Size = UDim2.new(0,300,0,160) end if position then loadingFrame.Position = position else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end local loadingBar = Instance.new("Frame") loadingBar.Name = "LoadingBar" loadingBar.BackgroundColor3 = Color3.new(0,0,0) loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255) loadingBar.Position = UDim2.new(0,0,0,41) loadingBar.Size = UDim2.new(1,0,0,30) loadingBar.Parent = loadingFrame local loadingGreenBar = Instance.new("ImageLabel") loadingGreenBar.Name = "LoadingGreenBar" loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053" loadingGreenBar.Position = UDim2.new(0,0,0,0) loadingGreenBar.Size = UDim2.new(0,0,1,0) loadingGreenBar.Visible = false loadingGreenBar.Parent = loadingBar local loadingPercent = Instance.new("TextLabel") loadingPercent.Name = "LoadingPercent" loadingPercent.BackgroundTransparency = 1 loadingPercent.Position = UDim2.new(0,0,1,0) loadingPercent.Size = UDim2.new(1,0,0,14) loadingPercent.Font = Enum.Font.Arial loadingPercent.Text = "0%" loadingPercent.FontSize = Enum.FontSize.Size14 loadingPercent.TextColor3 = Color3.new(1,1,1) loadingPercent.Parent = loadingBar local cancelButton = Instance.new("TextButton") cancelButton.Name = "CancelButton" cancelButton.Position = UDim2.new(0.5,-60,1,-40) cancelButton.Size = UDim2.new(0,120,0,40) cancelButton.Font = Enum.Font.Arial cancelButton.FontSize = Enum.FontSize.Size18 cancelButton.TextColor3 = Color3.new(1,1,1) cancelButton.Text = "Cancel" cancelButton.Style = Enum.ButtonStyle.RobloxButton cancelButton.Parent = loadingFrame local loadingName = Instance.new("TextLabel") loadingName.Name = "loadingName" loadingName.BackgroundTransparency = 1 loadingName.Size = UDim2.new(1,0,0,18) loadingName.Position = UDim2.new(0,0,0,2) loadingName.Font = Enum.Font.Arial loadingName.Text = name loadingName.TextColor3 = Color3.new(1,1,1) loadingName.TextStrokeTransparency = 1 loadingName.FontSize = Enum.FontSize.Size18 loadingName.Parent = loadingFrame local cancelButtonClicked = Instance.new("BindableEvent") cancelButtonClicked.Name = "CancelButtonClicked" cancelButtonClicked.Parent = cancelButton cancelButton.MouseButton1Click:connect(function() cancelButtonClicked:Fire() end) local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength) if percent and type(percent) ~= "number" then error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead") end local newSize = nil if percent < 0 then newSize = UDim2.new(0,0,1,0) elseif percent > 1 then newSize = UDim2.new(1,0,1,0) else newSize = UDim2.new(percent,0,1,0) end if tweenAction then if not tweenLength then error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument") end if (newSize.X.Scale > 0) then loadingGreenBar.Visible = true loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true) else loadingGreenBar:TweenSize( newSize, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, tweenLength, true, function() if (newSize.X.Scale < 0) then loadingGreenBar.Visible = false end end) end else loadingGreenBar.Size = newSize loadingGreenBar.Visible = (newSize.X.Scale > 0) end end loadingGreenBar.Changed:connect(function(prop) if prop == "Size" then loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%" end end) return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked end t.CreatePluginFrame = function (name,size,position,scrollable,parent) function createMenuButton(size,position,text,fontsize,name,parent) local button = Instance.new("TextButton",parent) button.AutoButtonColor = false button.Name = name button.BackgroundTransparency = 1 button.Position = position button.Size = size button.Font = Enum.Font.ArialBold button.FontSize = fontsize button.Text = text button.TextColor3 = Color3.new(1,1,1) button.BorderSizePixel = 0 button.BackgroundColor3 = Color3.new(20/255,20/255,20/255) button.MouseEnter:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 0 end) button.MouseLeave:connect(function ( ) if button.Selected then return end button.BackgroundTransparency = 1 end) return button end local dragBar = Instance.new("Frame",parent) dragBar.Name = tostring(name) .. "DragBar" dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) dragBar.BorderColor3 = Color3.new(0,0,0) if size then dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0) else dragBar.Size = UDim2.new(0,183,0,20) end if position then dragBar.Position = position end dragBar.Active = true dragBar.Draggable = true --dragBar.Visible = false dragBar.MouseEnter:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255) end) dragBar.MouseLeave:connect(function ( ) dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255) end) -- plugin name label local pluginNameLabel = Instance.new("TextLabel",dragBar) pluginNameLabel.Name = "BarNameLabel" pluginNameLabel.Text = " " .. tostring(name) pluginNameLabel.TextColor3 = Color3.new(1,1,1) pluginNameLabel.TextStrokeTransparency = 0 pluginNameLabel.Size = UDim2.new(1,0,1,0) pluginNameLabel.Font = Enum.Font.ArialBold pluginNameLabel.FontSize = Enum.FontSize.Size18 pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left pluginNameLabel.BackgroundTransparency = 1 -- close button local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar) local closeEvent = Instance.new("BindableEvent") closeEvent.Name = "CloseEvent" closeEvent.Parent = closeButton closeButton.MouseButton1Click:connect(function () closeEvent:Fire() closeButton.BackgroundTransparency = 1 end) -- help button local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar) local helpFrame = Instance.new("Frame",dragBar) helpFrame.Name = "HelpFrame" helpFrame.BackgroundColor3 = Color3.new(0,0,0) helpFrame.Size = UDim2.new(0,300,0,552) helpFrame.Position = UDim2.new(1,5,0,0) helpFrame.Active = true helpFrame.BorderSizePixel = 0 helpFrame.Visible = false helpButton.MouseButton1Click:connect(function( ) helpFrame.Visible = not helpFrame.Visible if helpFrame.Visible then helpButton.Selected = true helpButton.BackgroundTransparency = 0 local screenGui = getScreenGuiAncestor(helpFrame) if screenGui then if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0) else -- position on right hand side helpFrame.Position = UDim2.new(1,5,0,0) end else helpFrame.Position = UDim2.new(1,5,0,0) end else helpButton.Selected = false helpButton.BackgroundTransparency = 1 end end) local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar) minimizeButton.TextYAlignment = Enum.TextYAlignment.Top local minimizeFrame = Instance.new("Frame",dragBar) minimizeFrame.Name = "MinimizeFrame" minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255) minimizeFrame.BorderColor3 = Color3.new(0,0,0) minimizeFrame.Position = UDim2.new(0,0,1,0) if size then minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0) else minimizeFrame.Size = UDim2.new(0,183,0,50) end minimizeFrame.Visible = false local minimizeBigButton = Instance.new("TextButton",minimizeFrame) minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20) minimizeBigButton.Name = "MinimizeButton" minimizeBigButton.Size = UDim2.new(0,100,0,40) minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton minimizeBigButton.Font = Enum.Font.ArialBold minimizeBigButton.FontSize = Enum.FontSize.Size18 minimizeBigButton.TextColor3 = Color3.new(1,1,1) minimizeBigButton.Text = "Show" local separatingLine = Instance.new("Frame",dragBar) separatingLine.Name = "SeparatingLine" separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255) separatingLine.BorderSizePixel = 0 separatingLine.Position = UDim2.new(1,-18,0.5,-7) separatingLine.Size = UDim2.new(0,1,0,14) local otherSeparatingLine = separatingLine:clone() otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7) otherSeparatingLine.Parent = dragBar local widgetContainer = Instance.new("Frame",dragBar) widgetContainer.Name = "WidgetContainer" widgetContainer.BackgroundTransparency = 1 widgetContainer.Position = UDim2.new(0,0,1,0) widgetContainer.BorderColor3 = Color3.new(0,0,0) if not scrollable then widgetContainer.BackgroundTransparency = 0 widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255) end if size then if scrollable then widgetContainer.Size = size else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset) end else if scrollable then widgetContainer.Size = UDim2.new(0,163,0,400) else widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400) end end if position then widgetContainer.Position = position + UDim2.new(0,0,0,20) end local frame,control,verticalDragger = nil if scrollable then --frame for widgets frame,control = t.CreateTrueScrollingFrame() frame.Size = UDim2.new(1, 0, 1, 0) frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255) frame.BorderColor3 = Color3.new(0,0,0) frame.Active = true frame.Parent = widgetContainer control.Parent = dragBar control.BackgroundColor3 = Color3.new(72/255,72/255,72/255) control.BorderSizePixel = 0 control.BackgroundTransparency = 0 control.Position = UDim2.new(1,-21,1,1) if size then control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset) else control.Size = UDim2.new(0,21,0,400) end control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20) local fakeLine = Instance.new("Frame",control) fakeLine.Name = "FakeLine" fakeLine.BorderSizePixel = 0 fakeLine.BackgroundColor3 = Color3.new(0,0,0) fakeLine.Size = UDim2.new(0,1,1,1) fakeLine.Position = UDim2.new(1,0,0,0) verticalDragger = Instance.new("TextButton",widgetContainer) verticalDragger.ZIndex = 2 verticalDragger.AutoButtonColor = false verticalDragger.Name = "VerticalDragger" verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) verticalDragger.BorderColor3 = Color3.new(0,0,0) verticalDragger.Size = UDim2.new(1,20,0,20) verticalDragger.Position = UDim2.new(0,0,1,0) verticalDragger.Active = true verticalDragger.Text = "" local scrubFrame = Instance.new("Frame",verticalDragger) scrubFrame.Name = "ScrubFrame" scrubFrame.BackgroundColor3 = Color3.new(1,1,1) scrubFrame.BorderSizePixel = 0 scrubFrame.Position = UDim2.new(0.5,-5,0.5,0) scrubFrame.Size = UDim2.new(0,10,0,1) scrubFrame.ZIndex = 5 local scrubTwo = scrubFrame:clone() scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2) scrubTwo.Parent = verticalDragger local scrubThree = scrubFrame:clone() scrubThree.Position = UDim2.new(0.5,-5,0.5,2) scrubThree.Parent = verticalDragger local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent)) areaSoak.Name = "AreaSoak" areaSoak.Size = UDim2.new(1,0,1,0) areaSoak.BackgroundTransparency = 1 areaSoak.BorderSizePixel = 0 areaSoak.Text = "" areaSoak.ZIndex = 10 areaSoak.Visible = false areaSoak.Active = true local draggingVertical = false local startYPos = nil verticalDragger.MouseEnter:connect(function () verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255) end) verticalDragger.MouseLeave:connect(function () verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255) end) verticalDragger.MouseButton1Down:connect(function(x,y) draggingVertical = true areaSoak.Visible = true startYPos = y end) areaSoak.MouseButton1Up:connect(function ( ) draggingVertical = false areaSoak.Visible = false end) areaSoak.MouseMoved:connect(function(x,y) if not draggingVertical then return end local yDelta = y - startYPos if not control.ScrollDownButton.Visible and yDelta > 0 then return end if (widgetContainer.Size.Y.Offset + yDelta) < 150 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150) control.Size = UDim2.new (0,21,0,150) return end startYPos = y if widgetContainer.Size.Y.Offset + yDelta >= 0 then widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta) control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta ) end end) end local function switchMinimize() minimizeFrame.Visible = not minimizeFrame.Visible if scrollable then frame.Visible = not frame.Visible verticalDragger.Visible = not verticalDragger.Visible control.Visible = not control.Visible else widgetContainer.Visible = not widgetContainer.Visible end if minimizeFrame.Visible then minimizeButton.Text = "+" else minimizeButton.Text = "-" end end minimizeBigButton.MouseButton1Click:connect(function ( ) switchMinimize() end) minimizeButton.MouseButton1Click:connect(function( ) switchMinimize() end) if scrollable then return dragBar, frame, helpFrame, closeEvent else return dragBar, widgetContainer, helpFrame, closeEvent end end t.Help = function(funcNameOrFunc) --input argument can be a string or a function. Should return a description (of arguments and expected side effects) if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then return "Function CreatePropertyDropDownMenu. " .. "Arguments: (instance, propertyName, enumType). " .. "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'" end if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then return "Function CreateDropDownMenu. " .. "Arguments: (items, onItemSelected). " .. "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items" end if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then return "Function CreateMessageDialog. " .. "Arguments: (title, message, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button" end if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then return "Function CreateStyledMessageDialog. " .. "Arguments: (title, message, style, buttons). " .. "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm" end if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then return "Function GetFontHeight. " .. "Arguments: (font, fontSize). " .. "Side effect: returns the size in pixels of the given font + fontSize" end if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then end if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then return "Function CreateScrollingFrame. " .. "Arguments: (orderList, style) " .. "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)" end if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then return "Function CreateTrueScrollingFrame. " .. "Arguments: (nil) " .. "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit." end if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then return "Function AutoTruncateTextObject. " .. "Arguments: (textLabel) " .. "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument" end if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then return "Function CreateSlider. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then return "Function CreateSliderNew. " .. "Arguments: (steps, width, position) " .. "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on." end if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then return "Function CreateLoadingFrame. " .. "Arguments: (name, size, position) " .. "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog." end if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then return "Function CreateTerrainMaterialSelector. " .. "Arguments: (size, position) " .. "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected." end end --rbxsig%CqCG5zfc/XIjIEri/nYJ9ncJ3CVrBvc+dEV0dQ0iMjszaG45Oo0mMObtk/wOX16pMnwFbOo5OEnl4hHRNHan3AfjuqIGQGvXAnkfpO9PC3aX9Ekw8Y86aje2lzBqi4eikB6dWdf/Zfh/RORnavUxn3htyTMVZmaAd/Qc6eNOAc4=% --rbxassetid%48488235% --new playerlist by Zach Lindblad (fusroblox) --contact him for any revisions/issues -------------------- -- Super Util -------------------- local ADMINS = { iagoMAO = "rbxasset://textures/ui/admins/iagoMAO.png", winsupermario1234 = "rbxasset://textures/ui/admins/winsupermario1234.png", Carrot = "rbxasset://textures/ui/admins/carrot.png", coke = "rbxasset://textures/ui/admins/coke.png", khanglegos = "rbxasset://textures/ui/admins/khanglegos.png", QuackIAttack = "rbxasset://textures/ui/admins/QuackIAttack.png", romulo27 = "rbxasset://textures/ui/admins/romulo27.png", TheLivingBee = "rbxasset://textures/ui/admins/TheLivingBee.png", OliverA = 1, kinery = 1, Peridorky =1, Bitl = "rbxasset://textures/ui/admins/bitl.png", Raymonf = "rbxasset://textures/ui/admins/Raymonf.png", } --[[ Generic object Create function, which I am using to create Gui's Thanks to Stravant! --]] local Obj = {} function Obj.Create(guiType) return function(data) local obj = Instance.new(guiType) for k, v in pairs(data) do if type(k) == 'number' then v.Parent = obj else obj[k] = v end end return obj end end --[[ makes a full sized background for a guiobject @Args: imgName asset name of image to fill background @Return: background gui object --]] function MakeBackgroundGuiObj(imgName) return Obj.Create'ImageLabel' { Name = 'Background', BackgroundTransparency = 1, Image = imgName, Position = UDim2.new(0, 0, 0, 0), Size = UDim2.new(1,0,1,0), } end --[[ turns 255 integer color value to a color3 --]] function Color3I(r,g,b) return Color3.new(r/255,g/255,b/255) end --[[ Gets correct icon for builder's club status to display by name @Args: membershipType Enum of membership status @Return: string of image asset --]] function getMembershipTypeIcon(membershipType,playerName) if ADMINS[playerName]~=nil then if ADMINS[playerName] == 1 then return "rbxasset://textures/ui/admins/default.png" else return ADMINS[playerName] end elseif membershipType == Enum.MembershipType.None then return "" elseif membershipType == Enum.MembershipType.BuildersClub then return "rbxasset://textures/ui/TinyBcIcon.png" elseif membershipType == Enum.MembershipType.TurboBuildersClub then return "rbxasset://textures/ui/TinyTbcIcon.png" elseif membershipType == Enum.MembershipType.OutrageousBuildersClub then return "rbxasset://textures/ui/TinyObcIcon.png" else error("Unknown membershipType" .. membershipType) end end local function getFriendStatusIcon(friendStatus) if friendStatus == Enum.FriendStatus.Unknown or friendStatus == Enum.FriendStatus.NotFriend then return "" elseif friendStatus == Enum.FriendStatus.Friend then return "rbxasset://textures/ui/friend.png" elseif friendStatus == Enum.FriendStatus.FriendRequestSent then return "rbxasset://textures/ui/friendrequestsent.png" elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then return "rbxasset://textures/ui/friendrequestreceived.png" else error("Unknown FriendStatus: " .. friendStatus) end end --[[ Utility function to create buttons for the popup menus @Args: nparent what to parent this button to ntext text to put on this button index number index of this entry in menu last is this the last element of the popup menu @Return: a popup menu button --]] function MakePopupButton(nparent,ntext,index,last) local tobj = Obj.Create"ImageButton" { Name = 'ReportButton', BackgroundTransparency = 1, Position = UDim2.new(0,0,1*index,0), Size = UDim2.new(1, 0, 1, 0), ZIndex=9, Obj.Create'TextLabel' { Name = 'ButtonText', BackgroundTransparency = 1, Position = UDim2.new(.07, 0, .07, 0), Size = UDim2.new(.86,0,.86,0), Parent = HeaderFrame, Font = 'ArialBold', Text = ntext, FontSize = 'Size14', TextScaled = true, TextColor3 = Color3.new(1,1,1), TextStrokeTransparency = 1, ZIndex=9, }, Parent = nparent, } if index==0 then tobj.Image = 'http://www.roblox.com/asset/?id=97108784' elseif last then tobj.Image = 'http://www.roblox.com/asset/?id=97109175' else if index%2==1 then tobj.Image = 'http://www.roblox.com/asset/?id=97112126' else tobj.Image = 'http://www.roblox.com/asset/?id=97109338' end end return tobj end --[[ obligatory wait for child function @Args: parent Parent object to look for child in child name of child object to look for @Return: object waited for --]] function WaitForChild(parent,child) while not parent:FindFirstChild(child) do wait() debugprint(" child "..parent.Name.." waiting for "..child) end return parent[child] end --------------------------- -- Workspace Objects --------------------------- -- might want to move all this to an init function, wait for localplayer elsewhere local Players = game:GetService('Players') -- make sure this doesn't run on the server(it will if you dont do this) while not Players.LocalPlayer do Players.Changed:wait() end local LocalPlayer = Players.LocalPlayer local Mouse = LocalPlayer:GetMouse() local ScreenGui = Obj.Create"Frame" { Name = 'PlayerListScreen', Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, Parent = script.Parent -- LocalPlayer.PlayerGui -- use for switching into playergui mode } local MainFrame = Obj.Create"Frame" { Name = 'LeaderBoardFrame', Position = UDim2.new(1, -150, 0.005, 0), Size = UDim2.new(0, 150, 0, 800), BackgroundTransparency = 1, Parent = ScreenGui, } --frame used for expanding leaderstats when frame is 'focused' local FocusFrame = Obj.Create"Frame" { Name = 'FocusFrame', Position = UDim2.new(0, 0, 0, 0), Size = UDim2.new(1, 0, 0, 100), BackgroundTransparency = 1, Active = true, Parent = MainFrame, } local TemplateFrameYSize = 0.670000017 -- HEADER local HeaderFrame = Obj.Create"Frame" { Name = 'Header', BackgroundTransparency = 1, Position = UDim2.new(0,0,0,0), Size = UDim2.new(1, 0, .07, 0), Parent = MainFrame, MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94692054'), } local HeaderFrameHeight = HeaderFrame.Size.Y.Scale local MaximizeButton = Obj.Create"ImageButton" { Name = 'MaximizeButton', Active = true, BackgroundTransparency = 1, Position = UDim2.new(0, 0, 0, 0), Size = UDim2.new(1,0,1,0), Parent = HeaderFrame, } local HeaderName = Obj.Create"TextLabel" { Name = 'PlayerName', BackgroundTransparency = 1, Position = UDim2.new(0, 0, .01, 0), Size = UDim2.new(.98,0,.38,0), Parent = HeaderFrame, Font = 'ArialBold', Text = LocalPlayer.Name, FontSize='Size24', --TextScaled = true, TextColor3 = Color3.new(1,1,1), TextStrokeColor3 = Color3.new(0,0,0), TextStrokeTransparency = 0, TextXAlignment = 'Right', TextYAlignment = 'Center', } local HeaderScore = Obj.Create"TextLabel" { Name = 'PlayerScore', BackgroundTransparency = 1, Position = UDim2.new(0, 0, .4, 0), Size = UDim2.new(.98,0,0,30), Parent = HeaderFrame, Font = 'ArialBold', Text = '', FontSize='Size24', TextYAlignment = 'Top', --TextScaled = true, TextColor3 = Color3.new(1,1,1), TextStrokeTransparency = 1, TextXAlignment = 'Right', TextYAlignment = 'Top', } -- BOTTOM --used for shifting bottom frame for mouse over effects local BottomShiftFrame = Obj.Create"Frame" { Name= 'BottomShiftFrame', BackgroundTransparency = 1, Position = UDim2.new(0,0,HeaderFrameHeight,0), Size = UDim2.new(1,0,1,0), Parent=MainFrame, } local BottomFrame = Obj.Create"Frame" { Name = 'Bottom', BackgroundTransparency = 1, Position = UDim2.new(0,0,.07,0), Size = UDim2.new(1, 0, .03, 0), Parent = BottomShiftFrame, MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94754966'), } local ExtendButton = Obj.Create"ImageButton" { Name = 'bigbutton', Active = true, BackgroundTransparency = 1, Position = UDim2.new(0, 0, 0, 0), Size = UDim2.new(1,0,1.5,0), ZIndex = 3, Parent = BottomFrame, } local ExtendTab = Obj.Create"ImageButton" { Name = 'extendTab', Active = true, BackgroundTransparency = 1, Image = 'http://www.roblox.com/asset/?id=94692731', Position = UDim2.new(.608, 0, .3, 0), Size = UDim2.new(.3,0,.7,0), Parent = BottomFrame, } local TopClipFrame = Obj.Create"Frame" { Name = 'ListFrame', BackgroundTransparency = 1, Position = UDim2.new(-1,0,.07,0), Size = UDim2.new(2, 0, 1, 0), Parent = MainFrame, ClipsDescendants = true, } local BottomClipFrame = Obj.Create"Frame" { Name = 'BottomFrame', BackgroundTransparency = 1, Position = UDim2.new(0,0, - .8,0), Size = UDim2.new(1, 0, 1, 0), Parent = TopClipFrame, ClipsDescendants = true, } local ScrollBarFrame = Obj.Create"Frame" { Name = 'ScrollBarFrame', BackgroundTransparency = 1, Position = UDim2.new(.987,0,.8,0), Size = UDim2.new(.01, 0, .2, 0), Parent = BottomClipFrame, } local ScrollBar = Obj.Create"Frame" { Name = 'ScrollBar', BackgroundTransparency = 0, BackgroundColor3 = Color3.new(.2,.2,.2), Position = UDim2.new(0,0,0,0), Size = UDim2.new(1, 0, .5, 0), ZIndex = 5, Parent = ScrollBarFrame, } local ListFrame = Obj.Create"Frame" { Name = 'SubFrame', BackgroundTransparency = 1, Position = UDim2.new(0,0,.8,0), Size = UDim2.new(1, 0, 1, 0), Parent = BottomClipFrame, } local PopUpClipFrame = Obj.Create"Frame" { Name = 'PopUpFrame', BackgroundTransparency = 1, SizeConstraint='RelativeXX', Position = MainFrame.Position + UDim2.new( 0,-150,0,0), Size = UDim2.new(0,150,0,800), Parent = MainFrame, ClipsDescendants = true, ZIndex=9, } local PopUpPanel = Obj.Create"Frame" { Name = 'Panel', BackgroundTransparency = 1, Position = UDim2.new(1,0,0,0), Size = UDim2.new(1,0,.032,0), Parent = PopUpClipFrame, } local ReportPlayerButton = MakePopupButton(PopUpPanel,'Report Player',0) local FriendPlayerButton = MakePopupButton(PopUpPanel,'Friend',1,true) local PersonalServerPanel = Obj.Create"Frame" { Name = 'Panel', BackgroundTransparency = 1, Position = UDim2.new(1,0,0,0), Size = UDim2.new(1,0,.032,0), Parent = PopUpClipFrame, } local PSReportPlayerButton = MakePopupButton(PersonalServerPanel,'Report Player',0) local PSFriendPlayerButton = MakePopupButton(PersonalServerPanel,'Friend',1) local BanPlayerButton = MakePopupButton(PersonalServerPanel,'Ban',2) local VisitorButton = MakePopupButton(PersonalServerPanel,'Visitor',3) local MemberButton = MakePopupButton(PersonalServerPanel,'Member',4) local AdminButton = MakePopupButton(PersonalServerPanel,'Admin',5,true) local StatTitles = Obj.Create"Frame" { Name = 'StatTitles', BackgroundTransparency = 1, Position = UDim2.new(0,0,1,-10), Size = UDim2.new(1, 0, 0, 0), Parent = HeaderFrame, } local IsMinimized = Instance.new('BoolValue') local IsMaximized = Instance.new('BoolValue') local IsTabified = Instance.new('BoolValue') local AreNamesExpanded = Instance.new('BoolValue') local MiddleTemplate = Obj.Create"Frame" { Name = 'MidTemplate', BackgroundTransparency = 1, Position = UDim2.new(100,0,.07,0), Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0), Obj.Create'ImageLabel' { Name = 'BCLabel', Active = true, BackgroundTransparency = 1, Position = UDim2.new(.005, 5, .20, 0), Size = UDim2.new(0,16,0,16), SizeConstraint = 'RelativeYY', Image = "", ZIndex = 3, }, Obj.Create'ImageLabel' { Name = 'FriendLabel', Active = true, BackgroundTransparency = 1, Position = UDim2.new(.005, 5, .15, 0), Size = UDim2.new(0,16,0,16), SizeConstraint = 'RelativeYY', Image = "", ZIndex = 3, }, Obj.Create"ImageButton" { Name = 'ClickListener', Active = true, BackgroundTransparency = 1, Position = UDim2.new(.005, 1, 0, 0), Size = UDim2.new(.96,0,1,0), ZIndex = 3, }, Obj.Create"Frame" { Name = 'TitleFrame', BackgroundTransparency = 1, Position = UDim2.new(.01, 0, 0, 0), Size = UDim2.new(0,140,1,0), ClipsDescendants=true, Obj.Create"TextLabel" { Name = 'Title', BackgroundTransparency = 1, Position = UDim2.new(0, 5, 0, 0), Size = UDim2.new(100,0,1,0), Font = 'Arial', FontSize='Size14', TextColor3 = Color3.new(1,1,1), TextXAlignment = 'Left', TextYAlignment = 'Center', ZIndex = 3, }, }, Obj.Create"TextLabel" { Name = 'PlayerScore', BackgroundTransparency = 1, Position = UDim2.new(0, 0, 0, 0), Size = UDim2.new(1,0,1,0), Font = 'Arial', Text = '', FontSize='Size14', TextColor3 = Color3.new(1,1,1), TextXAlignment = 'Left', TextYAlignment = 'Center', ZIndex = 3, }, --Obj.Create'IntValue'{Name = 'ID'}, --Obj.Create'ObjectValue'{Name = 'Player'}, --Obj.Create'IntValue'{Name = 'Score'}, ZIndex = 3, } local MiddleBGTemplate = Obj.Create"Frame" { Name = 'MidBGTemplate', BackgroundTransparency = 1, Position = UDim2.new(100,0,.07,0), Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0), MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94692025'), } -- REPORT ABUSE OBJECTS local ReportAbuseShield = Obj.Create"TextButton" { Name = "ReportAbuseShield", Text = "", AutoButtonColor = false, Active = true, Visible = true, Size = UDim2.new(1,0,1,0), BackgroundColor3 = Color3I(51,51,51), BorderColor3 = Color3I(27,42,53), BackgroundTransparency = 1, } local ReportAbuseFrame = Obj.Create "Frame" { Name = "Settings", Position = UDim2.new(0.5, - 250, 0.5, - 200), Size = UDim2.new(0.0, 500, 0.0, 400), BackgroundTransparency = 1, Active = true, Parent = ReportAbuseShield, } local AbuseSettingsFrame = Obj.Create"Frame" { Name = "ReportAbuseStyle", Size = UDim2.new(1, 0, 1, 0), Active = true, BackgroundTransparency = 1, MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96488767'), -- 96480351'), Obj.Create"TextLabel" { Name = "Title", Text = "Report Abuse", TextColor3 = Color3I(221,221,221), Position = UDim2.new(0.5, 0, 0, 30), Font = Enum.Font.ArialBold, FontSize = Enum.FontSize.Size36, }, Obj.Create"TextLabel" { Name = "Description", Text = "This will send a complete report to a moderator. The moderator will review the chat log and take appropriate action.", TextColor3 = Color3I(221,221,221), Position = UDim2.new(.01, 0, 0, 55), Size = UDim2.new(.99, 0, 0, 40), BackgroundTransparency = 1, Font = Enum.Font.Arial, FontSize = Enum.FontSize.Size18, TextWrap = true, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, }, Obj.Create"TextLabel" { Name = "AbuseLabel", Text = "What did they do?", Font = Enum.Font.Arial, BackgroundTransparency = 1, FontSize = Enum.FontSize.Size18, Position = UDim2.new(0.025,0,0,140), Size = UDim2.new(0.4,0,0,36), TextColor3 = Color3I(255,255,255), TextXAlignment = Enum.TextXAlignment.Left, }, Obj.Create"TextLabel" { Name = "ShortDescriptionLabel", Text = "Short Description: (optional)", Font = Enum.Font.Arial, FontSize = Enum.FontSize.Size18, Position = UDim2.new(0.025,0,0,180), Size = UDim2.new(0.95,0,0,36), TextColor3 = Color3I(255,255,255), TextXAlignment = Enum.TextXAlignment.Left, BackgroundTransparency = 1, }, Obj.Create"TextLabel" { Name = "ReportingPlayerLabel", Text = "Reporting Player", BackgroundTransparency = 1, Font = Enum.Font.Arial, FontSize = Enum.FontSize.Size18, Position = UDim2.new(0.025,0,0,100), Size = UDim2.new(0.95,0,0,36), TextColor3 = Color3I(255,255,255), TextXAlignment = Enum.TextXAlignment.Left, Parent = AbuseSettingsFrame }, Parent = ReportAbuseFrame, } local AbusePlayerLabel = Obj.Create"TextLabel" { Name = "PlayerLabel", Text = "", BackgroundTransparency = 1, Font = Enum.Font.ArialBold, FontSize = Enum.FontSize.Size18, Position = UDim2.new(0.025,0,0,100), Size = UDim2.new(0.95,0,0,36), TextColor3 = Color3I(255,255,255), TextXAlignment = Enum.TextXAlignment.Right, Parent = AbuseSettingsFrame } local SubmitReportButton = Obj.Create"ImageButton" { Name = "SubmitReportBtn", Active = false, BackgroundTransparency = 1, Position = UDim2.new(.5, - 200, 1, - 80), Size = UDim2.new(0,150,0,50), AutoButtonColor = false, Image = 'http://www.roblox.com/asset/?id=96502438', -- 96501119', Parent = AbuseSettingsFrame, } local CancelReportButton = Obj.Create"ImageButton" { Name = "CancelBtn", BackgroundTransparency = 1, Position = UDim2.new(0.5, 50, 1, - 80), Size = UDim2.new(0,150,0,50), AutoButtonColor = true, Image = 'http://www.roblox.com/asset/?id=96500683', Parent = AbuseSettingsFrame, } local AbuseDescriptionWrapper = Obj.Create"Frame" { Name = "AbuseDescriptionWrapper", Position = UDim2.new(0.025,0,0,220), Size = UDim2.new(0.95,0,1, - 310), BackgroundColor3 = Color3I(0,0,0), BorderSizePixel = 0, Parent = AbuseSettingsFrame, } local AbuseDescriptionBox local OriginalAbuseDescriptionBox = Obj.Create"TextBox" { Name = "TextBox", Text = "", ClearTextOnFocus = false, Font = Enum.Font.Arial, FontSize = Enum.FontSize.Size18, Position = UDim2.new(0,3,0,3), Size = UDim2.new(1, - 6,1, - 6), TextColor3 = Color3I(255,255,255), TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top, TextWrap = true, BackgroundColor3 = Color3I(0,0,0), BorderSizePixel = 0, } local CalmingAbuseBox = Obj.Create'Frame' { Name = 'AbuseFeedbackBox', BackgroundTransparency = 1, Position=UDim2.new(0.25, 0, 0.300000012, 0), Size=UDim2.new(0.5, 0, 0.370000005, 0), MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96506233'), Obj.Create'TextLabel' { Name = 'Header', Position=UDim2.new(0,10,.05,0), Size=UDim2.new(1, -30, .15, 0), TextScaled = true, BackgroundTransparency = 1, TextXAlignment = Enum.TextXAlignment.Center, TextYAlignment = Enum.TextYAlignment.Top, Text = 'Thanks for your report!', TextColor3 = Color3.new(1,1,1), FontSize = Enum.FontSize.Size48, Font = 'ArialBold', }, Obj.Create'TextLabel' { Name = 'content', Position = UDim2.new(0,10,.20,0), Size = UDim2.new(1, -30, .40, 0), TextScaled = true, BackgroundTransparency = 1, TextColor3 = Color3.new(1,1,1), Text = 'Our moderators will review the chat logs and determine what happened. The other user is probably just trying to make you mad.\n\nIf anyone used swear words, inappropriate language, or threatened you in real life, please report them for Bad Words or Threats', TextWrapped = true, TextYAlignment = Enum.TextYAlignment.Top, FontSize = Enum.FontSize.Size24, Font = 'Arial', }, Obj.Create'ImageButton' { Name = "OkButton", BackgroundTransparency = 1, Position = UDim2.new(0.5, -75, 1, -80), Size = UDim2.new(0,150,0,50), AutoButtonColor = true, Image = 'http://www.roblox.com/asset/?id=96507959', } } local NormalAbuseBox = Obj.Create'Frame' { Name = 'AbuseFeedbackBox', BackgroundTransparency = 1, Position = UDim2.new(0.25, 0, 0.300000012, 0), Size = UDim2.new(0.5, 0, 0.370000005, 0), MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96506233'), Obj.Create'TextLabel' { Name = 'Header', Position = UDim2.new(0,10,.05,0), Size = UDim2.new(1, -30, .15, 0), TextScaled = true, BackgroundTransparency = 1, TextColor3 = Color3.new(1,1,1), TextXAlignment = Enum.TextXAlignment.Center, TextYAlignment = Enum.TextYAlignment.Top, Text = 'Thanks for your report!', FontSize = Enum.FontSize.Size48, Font ='ArialBold' }, Obj.Create'TextLabel' { Name = 'content', Position = UDim2.new(0,10,.20,0), Size = UDim2.new(1, -30, .15, 0), TextScaled = true, BackgroundTransparency = 1, TextColor3 = Color3.new(1,1,1), Text = "Our moderators will review the chat logs and determine what happened.", TextWrapped = true, TextYAlignment = Enum.TextYAlignment.Top, FontSize = Enum.FontSize.Size24, Font = 'Arial', }, Obj.Create'ImageButton' { Name = "OkButton", BackgroundTransparency = 1, Position = UDim2.new(0.5, -75, 1, -80), Size = UDim2.new(0,150,0,50), AutoButtonColor = true, Image = 'http://www.roblox.com/asset/?id=96507959', }, } local BigButton=Instance.new('ImageButton') BigButton.Size=UDim2.new(1,0,1,0) BigButton.BackgroundTransparency=1 BigButton.ZIndex=8 BigButton.Visible=false --BigButton.Active=false BigButton.Parent=ScreenGui local debugFrame = Obj.Create"Frame" { Name = 'debugframe', Position = UDim2.new(0, 0, 0, 0), Size = UDim2.new(0, 150, 0, 800),--0.99000001 BackgroundTransparency = 1, } local debugplayers = Obj.Create"TextLabel" { BackgroundTransparency = .8, Position = UDim2.new(0, 0, .01, 0), Size = UDim2.new(1,0,.5,0), Parent = debugFrame, Font = 'ArialBold', Text = '--', FontSize='Size14', TextWrapped=true, TextColor3 = Color3.new(1,1,1), TextStrokeColor3 = Color3.new(0,0,0), TextStrokeTransparency = 0, TextXAlignment = 'Right', TextYAlignment = 'Center', } local debugOutput = Obj.Create"TextLabel" { BackgroundTransparency = .8, Position = UDim2.new(0, 0, .5, 0), Size = UDim2.new(1,0,.5,0), Parent = debugFrame, Font = 'ArialBold', Text = '--', FontSize='Size14', TextWrapped=true, TextColor3 = Color3.new(1,1,1), TextStrokeColor3 = Color3.new(0,0,0), TextStrokeTransparency = 0, TextXAlignment = 'Right', TextYAlignment = 'Center', } --[[ simple function to toggle the display of debug output --]] local DebugPrintEnabled=true function debugprint(str) if DebugPrintEnabled then debugOutput.Text=str end end ------------------------- -- Script objects ------------------------- local RbxGui = t -- number of entries to show if you click minimize local DefaultEntriesOnScreen = 8 local Images = { bottomDark = '94691904', bottomLight = '94691940', midDark = '94691980', midLight = '94692025', LargeDark = '96098866', LargeLight = '96098920', LargeHeader = '96097470', NormalHeader = '94692054', LargeBottom = '96397271', -- '96098152', NormalBottom = '94754966', DarkBluePopupMid = '97114905', LightBluePopupMid = '97114905', DarkPopupMid = '97112126', LightPopupMid = '97109338', DarkBluePopupTop = '97114838', LightBluePopupTop = '', DarkPopupTop = '', LightPopupTop = '', DarkBluePopupBottom = '97114758', LightBluePopupBottom = '', DarkPopupBottom = '97109175', LightPopupBottom = '', } for _,i in pairs(Images) do Game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id="..i) end -- ordered array of 'score data', each entry has: -- Name(String) -- Priority(number) -- IsPrimary (bool, should it be shown in upper right) -- MaxLength (integer, of the length of the longest element for this column) local ScoreNames = {} -- prevents flipping in playerlist panels local AddId = 0 -- intermediate table form of all player entries in format of: -- Frame -- Player -- Score -- ID -- MyTeam (team ENRTY(not actual team) I am currently on) local PlayerFrames = {} -- intermediate ordered frame array, composed of Entrys of -- Frame -- MyTeam (my team object) -- MyPlayers ( an ordered array of all player frames in team ) -- AutoHide (bool saying whether it should be hidden) -- IsHidden (bool) -- ID (int to prevent flipping out of leaderboard, fun times) local TeamFrames = {} -- one special entry from teamFrames, for unaffiliated players, only shown if players non - empty local NeutralTeam = nil -- final 'to be displayed' list of frames local MiddleFrames = {} local MiddleFrameBackgrounds = {} local MiddleFrameHeight = .03 -- time of last click local LastClick = 0 local ButtonCooldown = .25 local OnIos = false pcall(function() OnIos = Game:GetService('UserInputService').TouchEnabled end) -- you get 200 of x screen space per stat added, start width 16% local BaseScreenXSize = 150 local SpacingPerStat = 10 --spacing between stats local MaximizedBounds = UDim2.new(.5,0,1,0) local MaximizedPosition = UDim2.new(.25,0,.1,0) local NormalBounds = UDim2.new(0,BaseScreenXSize, 0, 800) local NormalPosition = UDim2.new(1 , - BaseScreenXSize, 0.005, 0) local MinimizedBounds = UDim2.new(0, BaseScreenXSize, 0.99000001, 0) -- number of stats to show from leaderstats local NumPrimaryStats = 0 -- where the scroll par currently is positioned local ScrollPosition = 0.75999999 local IsDragging = false -- am I dragging the player list local DefaultBottomClipPos = BottomClipFrame.Position.Y.Scale local LastSelectedPlayerEntry = nil local SelectedPlayerEntry = nil local SelectedPlayer = nil -- locks(semaphores) for stopping race conditions local AddingFrameLock = false local ChangingOrderLock = false local AddingStatLock = false local BaseUpdateLock = false local WaitForClickLock = false local InPopupWaitForClick=false local PlayerChangedLock = false local NeutralTeamLock = false local ScrollWheelConnections = {} -- report abuse objects local AbuseName local Abuses = { "Bad Words or Threats", "Bad Username", "Talking about Dating", "Account Trading or Sharing", "Asking Personal Questions", "Rude or Mean Behavior", "False Reporting Me" } local UpdateAbuseFunction local AbuseDropDown, UpdateAbuseSelection local PrivilegeLevel = { Owner = 255, Admin = 240, Member = 128, Visitor = 10, Banned = 0, } local IsPersonalServer = not not game.Workspace:FindFirstChild("PSVariable") if IsPersonalServer then --THIS SHOULD NOT BE HERE GUYS, only keeping to perserve old functionality game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager") end game.Workspace.ChildAdded:connect(function(nchild) if nchild.Name=='PSVariable' and nchild:IsA('BoolValue') then IsPersonalServer=true --THIS SHOULD NOT BE HERE GUYS, only keeping to perserve old functionality game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager") end end) ------------------------------- -- Static Functions ------------------------------- function GetTotalEntries() return math.min(#MiddleFrameBackgrounds,DefaultEntriesOnScreen) end function GetEntryListLength() local numEnts=#PlayerFrames+#TeamFrames if NeutralTeam then numEnts=numEnts+1 end return numEnts end function AreAllEntriesOnScreen() return #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale <= 1 + BottomClipFrame.Position.Y.Scale end function GetLengthOfVisbleScroll() return 1 + BottomClipFrame.Position.Y.Scale end function GetMaxScroll() return BottomClipFrame.Position.Y.Scale * - 1 end -- can be optimized by caching when this varible changes function GetMinScroll() if AreAllEntriesOnScreen() then return GetMaxScroll() else return (GetMaxScroll() - (#MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale)) + (1 + BottomClipFrame.Position.Y.Scale) end end function AbsoluteToPercent(x,y) return Vector2.new(x,y)/ScreenGui.AbsoluteSize end --[[ tweens text transparency of element from starta to enda over length of time Warning: should be put in a Spawn call @Args: element textobject to tween transparency on starta alpha to start tweening enda alpha to end tweening on length how many seconds to spend tweening --]] function TweenTextTransparency(element,starta,enda,length) local startTime = time() while time() - startTime < length do element.TextTransparency = ((enda - starta) * ((time() - startTime)/length)) + starta wait(.01) end element.TextTransparency = enda end --[[ tweens background transparency of element from starta to enda over length of time Warning: should be put in a Spawn call @Args: element guiobject to tween transparency on starta alpha to start tweening enda alpha to end tweening on length how many seconds to spend tweening --]] function TweenBackgroundTransparency(element,starta,enda,length) local startTime = time() while time() - startTime < length do element.BackgroundTransparency = ((enda - starta) * ((time() - startTime)/length)) + starta wait(.01) end element.BackgroundTransparency = enda end --[[ UGLY UGLY HACK FUNCTION replace with some sort of global input catching A.S.A. FREAKING P. creates a fullsize gui element to catch next mouse up event(completeing a click) @Args: frameParent Object to parent fullscreen gui to polledFunction function to call on mouse moved events in this gui exitFunction function to call when click event is fired --]] function WaitForClick(frameParent,polledFunction,exitFunction) if WaitForClickLock then return end debugprint('waiting for click!') WaitForClickLock=true BigButton.Visible=true --BigButton.Active=true --BigButton.Parent=frameParent local upHappened=false local connection, connection2 connection2=BigButton.MouseMoved:connect( function(nx,ny) polledFunction(nx,ny) end) connection=BigButton.MouseButton1Up:connect(function(nx,ny) exitFunction(nx,ny) BigButton.Visible=false connection:disconnect() connection2:disconnect() debugprint('mouse up!') end) frameParent.AncestryChanged:connect(function(child,nparent) if child == frameParent and nparent ==nil then exitFunction(nx,ny) BigButton.Visible=false connection:disconnect() connection2:disconnect() debugprint("forced out of wait for click") end end) WaitForClickLock=false end --------------------------- --Personal Server Handling --------------------------- --[[ returns privlage level based on integer rank Note: these privilege levels seem completely arbitrary, but no documentation exists this is all from the old player list, really weird @Args: rank Integer rank value for player @Return Normalized integer value for rank? --]] function GetPrivilegeType(rank) if rank <= PrivilegeLevel['Banned'] then return PrivilegeLevel['Banned'] elseif rank <= PrivilegeLevel['Visitor'] then return PrivilegeLevel['Visitor'] elseif rank <= PrivilegeLevel['Member'] then return PrivilegeLevel['Member'] elseif rank <= PrivilegeLevel['Admin'] then return PrivilegeLevel['Admin'] else return PrivilegeLevel['Owner'] end end --[[ gives a player a new privilage rank Note: Very odd that I have to use loops with this instead of directly setting the rank but no documentation for personal server service exists @Args: player player to change rank of nrank new integer rank to give player --]] function SetPrivilegeRank(player,nrank) while player.PersonalServerRank<nrank do game:GetService("PersonalServerService"):Promote(player) end while player.PersonalServerRank>nrank do game:GetService("PersonalServerService"):Demote(player) end end --[[ called when player selects new privilege level from popup menu @Args: player player to set privileges on nlevel new privilege level for this player --]] function OnPrivilegeLevelSelect(player,nlevel) debugprint('setting privilege level') SetPrivilegeRank(player,nlevel) HighlightMyRank(player) PersonalServerPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) end --[[ Highlights current rank of this player in the popup menu @Args: player Player to check for rank on --]] function HighlightMyRank(player) BanPlayerButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid'] VisitorButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupMid'] MemberButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid'] AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupBottom'] local rank=player.PersonalServerRank if rank <= PrivilegeLevel['Banned'] then BanPlayerButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid'] elseif rank <= PrivilegeLevel['Visitor'] then VisitorButton.Image='http://www.roblox.com/asset/?id='..Images['DarkBluePopupMid'] elseif rank <= PrivilegeLevel['Member'] then MemberButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid'] elseif rank <= PrivilegeLevel['Admin'] then AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkBluePopupBottom'] end end BanPlayerButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Banned']) end) VisitorButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Visitor']) end) MemberButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Member']) end) AdminButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Admin']) end) -------------------------- -- Report abuse handling -------------------------- --[[ does final reporting of abuse on selected player, calls closeAbuseDialog --]] function OnSubmitAbuse() if SubmitReportButton.Active then if AbuseName and SelectedPlayer then AbuseSettingsFrame.Visible = false game.Players:ReportAbuse(SelectedPlayer, AbuseName, AbuseDescriptionBox.Text) if AbuseName == "Rude or Mean Behavior" or AbuseName == "False Reporting Me" then CalmingAbuseBox.Parent = ReportAbuseShield else debugprint('opening abuse box') NormalAbuseBox.Parent = ReportAbuseShield end else CloseAbuseDialog() end end end --[[ opens the abuse dialog, initialises text to display selectedplayer --]] function OpenAbuseDialog() debugprint('adding report dialog') AbusePlayerLabel.Text = SelectedPlayer.Name --AbuseDescriptionBox.Text = "" PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) AbuseDescriptionBox=OriginalAbuseDescriptionBox:Clone() AbuseDescriptionBox.Parent = AbuseDescriptionWrapper ReportAbuseShield.Parent = ScreenGui end --[[ resets and closes abuse dialog --]] function CloseAbuseDialog() AbuseName = nil SubmitReportButton.Active = false SubmitReportButton.Image = 'http://www.roblox.com/asset/?id=96502438' -- 96501119', AbuseDescriptionBox:Destroy() CalmingAbuseBox.Parent = nil NormalAbuseBox.Parent = nil ReportAbuseShield.Parent = nil AbuseSettingsFrame.Visible = true end --[[ creates dropdownbox, registers all listeners for abuse dialog --]] function InitReportAbuse() UpdateAbuseFunction = function(abuseText) AbuseName = abuseText if AbuseName and SelectedPlayer then SubmitReportButton.Active = true SubmitReportButton.Image = 'http://www.roblox.com/asset/?id=96501119' end end AbuseDropDown, UpdateAbuseSelection = RbxGui.CreateDropDownMenu(Abuses, UpdateAbuseFunction, true) AbuseDropDown.Name = "AbuseComboBox" AbuseDropDown.Position = UDim2.new(0.425, 0, 0, 142) AbuseDropDown.Size = UDim2.new(0.55,0,0,32) AbuseDropDown.Parent = AbuseSettingsFrame CancelReportButton.MouseButton1Click:connect(CloseAbuseDialog) SubmitReportButton.MouseButton1Click:connect(OnSubmitAbuse) ReportPlayerButton.MouseButton1Click:connect(function() BigButton.Visible=false OpenAbuseDialog() end) PSReportPlayerButton.MouseButton1Click:connect(function() BigButton.Visible=false OpenAbuseDialog() end) CalmingAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog) NormalAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog) end ------------------------------------- -- Friend/unfriending ------------------------------------- --[[ gets enum val of friend status, uses pcall for some reason?(from old playerlist) @Args: player player object to check if friends with @Return: enum of friend status --]] local function GetFriendStatus(player) if player == game.Players.LocalPlayer then return Enum.FriendStatus.NotFriend else local success, result = pcall(function() return game.Players.LocalPlayer:GetFriendStatus(player) end) if success then return result else return Enum.FriendStatus.NotFriend end end end --[[ Updates text on popup friend button of SelectedPlayer called when popup opens --]] function OnFriendPopUpOpen() local friendButton if IsPersonalServer and LocalPlayer.PersonalServerRank >= PrivilegeLevel['Admin'] then friendButton=PSFriendPlayerButton else friendButton=FriendPlayerButton end local friendStatus=GetFriendStatus(SelectedPlayer) debugprint('status: ' .. tostring(friendStatus)) if friendStatus==Enum.FriendStatus.Friend then friendButton:FindFirstChild('ButtonText').Text='UnFriend Player' elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then friendButton:FindFirstChild('ButtonText').Text='Send Friend Request' elseif friendStatus==Enum.FriendStatus.FriendRequestSent then friendButton:FindFirstChild('ButtonText').Text='Revoke Friend Request' elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then friendButton:FindFirstChild('ButtonText').Text='Accept Friend Request' end end --[[ when friend button is clicked, tries to take appropriate action, based on current friend status with SelectedPlayer --]] function OnFriendButtonSelect() BigButton.Visible=false local friendStatus=GetFriendStatus(SelectedPlayer) if friendStatus==Enum.FriendStatus.Friend then LocalPlayer:RevokeFriendship(SelectedPlayer) elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then LocalPlayer:RequestFriendship(SelectedPlayer) elseif friendStatus==Enum.FriendStatus.FriendRequestSent then LocalPlayer:RevokeFriendship(SelectedPlayer) elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then LocalPlayer:RequestFriendship(SelectedPlayer) end PersonalServerPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) end PSFriendPlayerButton.MouseButton1Click:connect(OnFriendButtonSelect) FriendPlayerButton.MouseButton1Click:connect(OnFriendButtonSelect) ------------------------------------ -- Player Entry Handling ------------------------------------ --[[ used by lua's table.sort to sort player entries --]] function PlayerSortFunction(a,b) -- prevents flipping out leaderboard if a['Score'] == b['Score'] then return a['ID'] < b['ID'] end if not a['Score'] then return false end if not b['Score'] then return true end return a['Score'] < b['Score'] end --------------------------------- -- Stat Handling --------------------------------- -- removes and closes all leaderboard stuffs function BlowThisPopsicleStand() --ScreenGui:Destroy() --script:Destroy() --time to make the fanboys rage... Tabify() end --[[ used by lua's table.sort to prioritize score entries --]] function StatSort(a,b) -- primary stats should be shown before all others if a.IsPrimary ~= b.IsPrimary then return a.IsPrimary end -- if priorities are equal, then return the first added one if a.Priority == b.Priority then return a.AddId < b.AddId end return a.Priority < b.Priority end --[[ doing WAAY too much here, for optimization update only your team @Args: playerEntry Entry of player who had a stat change property Name of stat changed --]] function StatChanged(playerEntry,property) -- if(playerEntry['MyTeam']) then -- UpdateSingleTeam(playerEntry['MyTeam']) -- else BaseUpdate() -- end end --[[ Called when stat is added if playerEntry is localplayer, will add to score names and re-sort the stats, and resize the width of the leaderboard for all players, will add a listener for if this stat changes if stat is a string value, crashes the leaderboard Note:change crash to a 'tabify' leaderboard later @Args: nchild new child value to leaderstats playerEntry entry this stat was added to --]] function StatAdded(nchild,playerEntry) -- dont re - add a leaderstat I alreday have while AddingStatLock do debugprint('in stat added function lock') wait(1/30) end AddingStatLock = true if not (nchild:IsA('StringValue') or nchild:IsA('IntValue') or nchild:IsA('BoolValue') or nchild:IsA('NumberValue') or nchild:IsA('DoubleConstrainedValue') or nchild:IsA('IntConstrainedValue')) then BlowThisPopsicleStand() else local haveScore = false for _,i in pairs(ScoreNames) do if i['Name']==nchild.Name then haveScore=true end end if not haveScore then local nstat = {} nstat['Name'] = nchild.Name nstat['Priority'] = 0 if(nchild:FindFirstChild('Priority')) then nstat['Priority'] = nchild.Priority end nstat['IsPrimary'] = false if(nchild:FindFirstChild('IsPrimary')) then nstat['IsPrimary'] = true end if(nstat['IsPrimary']) then NumPrimaryStats = NumPrimaryStats + 1 end nstat.AddId = AddId AddId = AddId + 1 table.insert(ScoreNames,nstat) table.sort(ScoreNames,StatSort) UpdateMaximize() end end AddingStatLock = false StatChanged(playerEntry) nchild.Changed:connect(function(property) StatChanged(playerEntry,property) end) end --[[ Called when stat is removed from player for all players, destroys the stat frame associated with this value, then calls statchanged(to resize frame) if playerEntry==localplayer, will remove from scorenames @Args: nchild ___value to be removed playerEntry entry of player value is being removed from --]] function StatRemoved(nchild,playerEntry) while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end AddingStatLock = true if playerEntry['Frame']:FindFirstChild(nchild.Name) then debugprint('Destroyed frame!') playerEntry['Frame'][nchild.Name].Parent = nil end if playerEntry['Player'].Name == LocalPlayer.Name then for i,val in ipairs(ScoreNames) do if val['IsPrimary'] then NumPrimaryStats = NumPrimaryStats - 1 end if val['Name'] == nchild.Name then table.remove(ScoreNames,i) end end end AddingStatLock = false StatChanged(playerEntry) end --[[ clears all stats from a given playerEntry used when leaderstats are removed, or when new leaderstats are added(for weird edge case)+ --]] function RemoveAllStats(playerEntry) while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end AddingStatLock = true for i,val in ipairs(ScoreNames) do if playerEntry['Frame']:FindFirstChild(val['Name']) then debugprint('Destroyed frame!') playerEntry['Frame'][val['Name']].Parent = nil end if playerEntry['Player'].Name == LocalPlayer.Name then NumPrimaryStats = NumPrimaryStats - 1 end end if playerEntry['Player'].Name == LocalPlayer.Name then NumPrimaryStats = NumPrimaryStats - 1 end AddingStatLock = false StatChanged(playerEntry) end function GetScoreValue(score) if score:IsA('DoubleConstrainedValue') or score:IsA('IntConstrainedValue') then return score.ConstrainedValue elseif score:IsA('BoolValue') then if score.Value then return 1 else return 0 end else return score.Value end end --[[ --]] function MakeScoreEntry(entry,scoreval,panel) if not panel:FindFirstChild('PlayerScore') then return end local nscoretxt = panel:FindFirstChild('PlayerScore'):Clone() local thisScore = nil --here lies the resting place of a once great and terrible bug --may its treachery never be forgoten, lest its survivors fall for it again --RIP the leaderstat bug, oct 2012-nov 2012 wait() if entry['Player']:FindFirstChild('leaderstats') then thisScore = entry['Player']:FindFirstChild('leaderstats'):FindFirstChild(scoreval['Name']) else return end if not entry['Player'].Parent then return end nscoretxt.Name = scoreval['Name'] nscoretxt.Text = tostring(GetScoreValue(thisScore)) if scoreval['Name'] == ScoreNames[1]['Name'] then debugprint('changing score') entry['Score'] = GetScoreValue(thisScore) if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end end thisScore.Changed:connect(function() if not thisScore.Parent then return end if scoreval['Name'] == ScoreNames[1]['Name'] then entry['Score'] = GetScoreValue(thisScore) if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end end nscoretxt.Text = tostring(GetScoreValue(thisScore)) BaseUpdate() end) return nscoretxt end function CreateStatTitle(statName) local ntitle = MiddleTemplate:FindFirstChild('PlayerScore'):Clone() ntitle.Name = statName ntitle.Text = statName -- ntitle if IsMaximized.Value then ntitle.TextTransparency = 0 else ntitle.TextTransparency = 1 end ntitle.Parent = StatTitles end function RecreateScoreColumns(ptable) while AddingStatLock do debugprint ('In Adding Stat Lock2') wait(1/30) end AddingStatLock = true local Xoffset=BaseScreenXSize --current offset from left local maxXOffset=Xoffset local MaxSizeColumn=0 --max size for this column -- foreach known leaderstat for j = 1, #ScoreNames,1 do local scoreval = ScoreNames[j] --if scoreval['ColumnSize'] then -- MaxSizeColumn=0--scoreval['ColumnSize'] --else MaxSizeColumn=0 --end -- for each entry in this player table for i,entry in ipairs(ptable) do local panel = entry['Frame'] local tplayer = entry['Player'] -- if this panel does not have an element named after this stat if not panel:FindFirstChild(scoreval['Name']) then -- make an entry for this object local nentry = MakeScoreEntry(entry,scoreval,panel) if nentry then debugprint('adding '..nentry.Name..' to '..entry['Player'].Name ) nentry.Parent = panel -- add score to team if entry['MyTeam'] and entry['MyTeam'] ~= NeutralTeam and not entry['MyTeam']['Frame']:FindFirstChild(scoreval['Name']) then local ntitle = nentry:Clone() ntitle.Parent = entry['MyTeam']['Frame'] end end end scoreval['XOffset']=Xoffset if panel:FindFirstChild(scoreval['Name']) then MaxSizeColumn=math.max(MaxSizeColumn,panel[scoreval['Name']].TextBounds.X) end end -- add stat title to top bar if not StatTitles:FindFirstChild(scoreval['Name']) then CreateStatTitle(scoreval['Name']) end if AreNamesExpanded.Value then MaxSizeColumn=math.max(MaxSizeColumn,StatTitles[scoreval['Name'] ].TextBounds.X) StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(0,Xoffset,0,0),'Out','Quad',.25,true) else StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0),'Out','Quad',.25,true) end scoreval['ColumnSize']=MaxSizeColumn Xoffset= Xoffset+SpacingPerStat+MaxSizeColumn maxXOffset=math.max(Xoffset,maxXOffset) end --print(maxXOffset) NormalBounds = UDim2.new(0, maxXOffset,0,800) NormalPosition = UDim2.new(1 , -NormalBounds.X.Offset, NormalPosition.Y.Scale, 0) UpdateHeaderNameSize() UpdateMaximize() AddingStatLock = false end --------------------------- -- Minimizing and maximizing --------------------------- function ToggleMinimize() IsMinimized.Value = not IsMinimized.Value end function ToggleMaximize() IsMaximized.Value = not IsMaximized.Value end function Tabify() IsTabified.Value= true IsMaximized.Value=false IsMinimized.Value=true UpdateMinimize() IsTabified.Value= true ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Quad',1,true) end function UnTabify() if IsTabified.Value then IsTabified.Value= false ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Quad',1,true) end end --[[ Does more than it looks like monitors positions of the clipping frames and bottom frames called from EVERYWHERE --]] function UpdateMinimize() if IsMinimized.Value then if IsMaximized.Value then ToggleMaximize() end if not IsTabified.Value then MainFrame:TweenSizeAndPosition(UDim2.new(0.010, HeaderName.TextBounds.X, NormalBounds.Y.Scale,NormalBounds.Y.Offset), UDim2.new(.990, -HeaderName.TextBounds.X, NormalPosition.Y.Scale,0),'Out','Quad',1,true) else MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true) end BottomClipFrame:TweenPosition(UDim2.new(0,0,DefaultBottomClipPos - (((GetTotalEntries()) * MiddleTemplate.Size.Y.Scale)),0), "Out", "Linear", .25,true) BottomFrame:TweenPosition(UDim2.new(0,0,0,0), "Out", "Linear", .25,true) FocusFrame.Size=UDim2.new(1,0,HeaderFrameHeight,0) ExtendTab.Image = 'http://www.roblox.com/asset/?id=94692731' else if not IsMaximized.Value then MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true) end BottomClipFrame:TweenPosition(UDim2.new(0,0,DefaultBottomClipPos,0), "Out", "Linear", .25,true) BottomFrame:TweenPosition(UDim2.new(0,0,((GetTotalEntries()) * MiddleTemplate.Size.Y.Scale),0), "Out", "Linear", .25,true) FocusFrame.Size=UDim2.new(1,0,((GetTotalEntries()) * MiddleTemplate.Size.Y.Scale) + HeaderFrameHeight,0) ExtendTab.Image = 'http://www.roblox.com/asset/?id=94825585' end end --[[ Manages the position/size of the mainFrame, swaps out different resolution images for the frame fades in and out the stat names, moves position of headername and header score --]] function UpdateMaximize() if IsMaximized.Value then --undo any 'name showing', without invoking base update if AreNamesExpanded.Value then CloseNames() for j = 1, #ScoreNames,1 do local scoreval = ScoreNames[j] StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0),'Out','Quad',.25,true) end end if IsMinimized.Value then ToggleMinimize() else UpdateMinimize() end MainFrame:TweenSizeAndPosition(MaximizedBounds,MaximizedPosition,'Out','Quad',1,true) HeaderScore:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true) HeaderName:TweenPosition(UDim2.new( - .1, - HeaderScore.TextBounds.x,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true) HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeHeader'] BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeBottom'] for index, i in ipairs(MiddleFrameBackgrounds) do if (index%2) ~= 1 then i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeDark'] else i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeLight'] end end for index, i in ipairs(MiddleFrames) do if i:FindFirstChild('ClickListener') then i.ClickListener.Size = UDim2.new(.974,0,i.ClickListener.Size.Y.Scale,0) end for j=1, #ScoreNames,1 do local scoreval = ScoreNames[j] if i:FindFirstChild(scoreval['Name']) then i[scoreval['Name']]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0), "Out", "Linear", .25,true) end end end for i,entry in ipairs(PlayerFrames) do WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0) end for i,entry in ipairs(TeamFrames) do WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0) end else if not IsMinimized.Value then MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true) end HeaderScore:TweenPosition(UDim2.new(0,0,.4,0), "Out", "Linear", .25,true) HeaderName:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true) HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalHeader'] BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalBottom'] for index, i in ipairs(MiddleFrameBackgrounds) do if index%2 ~= 1 then i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midDark'] else i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midLight'] end end for index, i in ipairs(MiddleFrames) do if i:FindFirstChild('ClickListener') then i.ClickListener.Size = UDim2.new(.96,0,i.ClickListener.Size.Y.Scale,0) for j=1, #ScoreNames,1 do local scoreval = ScoreNames[j] --print(scoreval['XOffset']) if i:FindFirstChild(scoreval['Name']) and scoreval['XOffset'] then --print('updateing stat position: ' .. scoreval['Name']) i[scoreval['Name']]:TweenPosition(UDim2.new(0,scoreval['XOffset'],0,0), "Out", "Linear", .25,true) end end end end if not AreNamesExpanded.Value then for _,i in pairs(StatTitles:GetChildren()) do Spawn(function()TweenTextTransparency(i,i.TextTransparency,1,.25) end) end end for i,entry in ipairs(TeamFrames) do WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0) end for i,entry in ipairs(PlayerFrames) do WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0) end end end function ExpandNames() if #ScoreNames ~= 0 then for _,i in pairs(StatTitles:GetChildren()) do Spawn(function()TweenTextTransparency(i,i.TextTransparency,0,.25) end) end HeaderFrameHeight=.09 --as of writing, this and 'CloseNames' are the only places headerframe is resized HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0), HeaderFrame.Position,'Out','Quad',.25,true) TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Quad',.25,true) BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Quad', .25,true) AreNamesExpanded.Value=true end end function CloseNames() if #ScoreNames ~= 0 then HeaderFrameHeight=.07 if not (IsMaximized.Value) then for _,i in pairs(StatTitles:GetChildren()) do Spawn(function()TweenTextTransparency(i,i.TextTransparency,1,.25) end) end end BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Quad', .25,true) HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0), HeaderFrame.Position,'Out','Quad',.25,true) TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Quad',.25,true) AreNamesExpanded.Value=false end end function OnScrollWheelMove(direction) if not (IsTabified.Value or IsMinimized.Value) then local StartFrame = ListFrame.Position local newFrameY = math.max(math.min(StartFrame.Y.Scale + (direction),GetMaxScroll()),GetMinScroll()) ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset) UpdateScrollPosition() end end function AttachScrollWheel() if ScrollWheelConnections then return end local pmouse = LocalPlayer:GetMouse() ScrollWheelConnections = {} table.insert(ScrollWheelConnections,pmouse.WheelForward:connect(function() OnScrollWheelMove(.05) end)) table.insert(ScrollWheelConnections,pmouse.WheelBackward:connect(function() OnScrollWheelMove(-.05) end)) end function DetachScrollWheel() if ScrollWheelConnections then for _,i in pairs(ScrollWheelConnections) do i:disconnect() end end ScrollWheelConnections=nil end FocusFrame.MouseEnter:connect(function() if not (IsMaximized.Value or IsMinimized.Value or IsTabified.Value) then ExpandNames() AttachScrollWheel() BaseUpdate() if IsTabified.Value then Tabify() end end end) FocusFrame.MouseLeave:connect(function() --if not (IsMaximized.Value or IsMinimized.Value) then CloseNames() DetachScrollWheel() BaseUpdate() if IsTabified.Value then Tabify() end --end end) ------------------------ -- Scroll Bar functions ------------------------ --[[ updates whether the scroll bar should be showing, if it is showing, updates the size of it --]] function UpdateScrollBarVisibility() if AreAllEntriesOnScreen() then ScrollBar.BackgroundTransparency = 1 else ScrollBar.BackgroundTransparency = 0 UpdateScrollBarSize() end end --[[ updates size of scrollbar depending on how many entries exist --]] function UpdateScrollBarSize() local entryListSize = #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale local shownAreaSize = ((BottomClipFrame.Position.Y.Scale) + 1) ScrollBar.Size = UDim2.new(1,0,shownAreaSize/entryListSize,0) end --[[ updates position of listframe so that no gaps at the bottom or top of the list are visible updates position of scrollbar to match what parts of the list are visible --]] function UpdateScrollPosition() local minPos = GetMinScroll() local maxPos = GetMaxScroll() local scrollLength = maxPos - minPos local yscrollpos=math.max(math.min(ListFrame.Position.Y.Scale,maxPos),minPos) ListFrame.Position=UDim2.new(ListFrame.Position.X.Scale,ListFrame.Position.X.Offset,yscrollpos,ListFrame.Position.Y.Offset) local adjustedLength = 1 - ScrollBar.Size.Y.Scale ScrollBar.Position = UDim2.new(0,0,adjustedLength - (adjustedLength * ((ListFrame.Position.Y.Scale - minPos)/scrollLength)),0) end --[[ WARNING:this is in a working state, but uses massive hacks revize when global input is available Manages scrolling of the playerlist on mouse drag --]] function StartDrag() Delay(0,function() debugprint('Got Click') local stopDrag = false local function dragExit() debugprint('undone click') stopDrag = true end local startY = nil --AbsoluteToPercent(Mouse.X,Mouse.Y).Y local StartFrame = ListFrame.Position local function dragpoll(nx,ny) if not startY then startY = AbsoluteToPercent(nx,ny).Y end local nowY = AbsoluteToPercent(nx,ny).Y local newFrameY if OnIos then newFrameY = math.max(math.min(StartFrame.Y.Scale + (nowY - startY),GetMaxScroll()),GetMinScroll()) else newFrameY = math.max(math.min(StartFrame.Y.Scale - (nowY - startY),GetMaxScroll()),GetMinScroll()) end ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset) UpdateScrollPosition() end Spawn(function() WaitForClick(ScreenGui,dragpoll,dragExit) end) end) end ------------------------------- -- Input Callback functions ------------------------------- IsMaximized.Value=false IsMinimized.Value=false IsMaximized.Changed:connect(UpdateMaximize) IsMinimized.Changed:connect(UpdateMinimize) ExtendButton.MouseButton1Click:connect(function() if(time() - LastClick < ButtonCooldown) then return end LastClick = time() UnTabify() ToggleMinimize() end) MaximizeButton.MouseButton1Click:connect(function() if(time() - LastClick < ButtonCooldown) then return end LastClick = time() if IsTabified.Value then UnTabify() else ToggleMaximize() end end) MaximizeButton.MouseButton2Click:connect(function() if(time() - LastClick < ButtonCooldown) then return end LastClick = time() if IsTabified.Value then UnTabify() else Tabify() end end) ------------------------------- -- MiddleFrames management ------------------------------- --[[ adds a background frame to the listframe --]] function AddMiddleBGFrame() local nBGFrame = MiddleBGTemplate:Clone() nBGFrame.Position = UDim2.new(.5,0,((#MiddleFrameBackgrounds) * nBGFrame.Size.Y.Scale),0) if (#MiddleFrameBackgrounds+1)%2 ~= 1 then if IsMaximized.Value then nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeDark'] else nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midDark'] end else if IsMaximized.Value then nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeLight'] else nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midLight'] end end nBGFrame.Parent = ListFrame table.insert(MiddleFrameBackgrounds,nBGFrame) if not IsMinimized.Value then -- BottomFrame:TweenPosition(UDim2.new(0,0,((#MiddleFrameBackgrounds) * nBGFrame.Size.Y.Scale) + HeaderFrameHeight,0), "Out", "Quad", .5,true) UpdateMinimize() end end --[[ removes a background from from the listframe --]] function RemoveMiddleBGFrame() MiddleFrameBackgrounds[#MiddleFrameBackgrounds]:Destroy() table.remove(MiddleFrameBackgrounds,#MiddleFrameBackgrounds) if not IsMinimized.Value then -- BottomFrame:TweenPosition(UDim2.new(0,0,((#MiddleFrameBackgrounds) * MiddleTemplate.Size.Y.Scale) + HeaderFrameHeight,0), "Out", "Quad", .5) UpdateMinimize() end end ------------------------------- -- Player Callback functions ------------------------------- local FONT_SIZES = {'Size8','Size9','Size10','Size11','Size12','Size14','Size24','Size36','Size48'} --[[ note:should probably set to something other than mainFrame.AbsoluteSize, should work for now if textbounds ever works on textscaled, switch to that :( --]] function ChangeHeaderName(nname) HeaderName.Text = nname UpdateHeaderNameSize() end --[[ Will fit the player's name to the bounds of the header called on resize of the window and playedr name change events HACK: cannot use 'Textscaled' due to unable to find text bounds when scaled --]] function UpdateHeaderNameSize() local tHeader= HeaderName:Clone() tHeader.Position=UDim2.new(2,0,2,0) tHeader.Parent=ScreenGui local fSize=7 --Size24 in table tHeader.FontSize=FONT_SIZES[fSize] Delay(.2,function() while tHeader.TextBounds.x==0 do wait(1/30) end while tHeader.TextBounds.x-(NormalBounds.X.Offset) > 1 do fSize=fSize-1 tHeader.FontSize=FONT_SIZES[fSize] wait(.2) end HeaderName.FontSize=tHeader.FontSize tHeader:Destroy() end) end ScreenGui.Changed:connect(UpdateHeaderNameSize) --[[ called only when the leaderstats object is added to a given player entry removes old stats, adds any existing stats, and sets up listeners for new stats @Args: playerEntry A reference to the ENTRY(table) of the player who had leaderstats added --]] function LeaderstatsAdded(playerEntry) --RemoveAllStats(playerEntry) local nplayer = playerEntry['Player'] for _,i in pairs(nplayer.leaderstats:GetChildren()) do StatAdded(i,playerEntry) end nplayer.leaderstats.ChildAdded:connect(function(nchild) StatAdded(nchild,playerEntry) end) nplayer.leaderstats.ChildRemoved:connect(function(nchild) StatRemoved(nchild,playerEntry) end) end --[[ called when leaderstats object is removed from play in player entry Note: may not be needed, might be able to just rely on leaderstats added @Args: oldLeaderstats leaderstats object to be removed playerEntry A reference to the ENTRY(table) of the player --]] function LeaderstatsRemoved(oldLeaderstats,playerEntry) while AddingFrameLock do debugprint('waiting to insert '..playerEntry['Player'].Name) wait(1/30) end AddingFrameLock = true RemoveAllStats(playerEntry) AddingFrameLock = false end --[[ prepares the needed movingpanel to be tweened on screen, and updates the position of the popup clip frame to match the selected player frame's position @Args: movingPanel The popup panel to tween on screen --]] function InitMovingPanel(movingPanel) PopUpClipFrame.Parent= SelectedPlayerEntry['Frame'] PopUpClipFrame.Position = UDim2.new( 0,-PopUpClipFrame.Size.X.Offset,0,0) movingPanel:TweenPosition(UDim2.new(0,0,0,0), "Out", "Quad", .5,true) OnFriendPopUpOpen() if IsPersonalServer then HighlightMyRank(SelectedPlayer) end WaitForClick(ScreenGui,function() end,function(nx,ny) movingPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) --connection:disconnect() end) end --[[ Called when a player entry in the leaderboard is clicked either will highlight entry and start the drag event, or open a popup menu @Args: entry the player entry clicked --]] function OnPlayerEntrySelect(entry) local movingPanel --if this is a personal server, and you are an admin and the selected person is a lower rank than you, then... if IsPersonalServer and LocalPlayer.PersonalServerRank >= PrivilegeLevel['Admin'] and LocalPlayer.PersonalServerRank > SelectedPlayer.PersonalServerRank then --and LocalPlayer.PersonalServerRank>entry['Player'].PersonalServerRank then movingPanel=PersonalServerPanel else movingPanel=PopUpPanel end if entry == SelectedPlayerEntry and SelectedPlayer~=LocalPlayer and SelectedPlayer.userId>1 and LocalPlayer.userId>1 then InPopupWaitForClick=true WaitForClick(ScreenGui,function() end, function() InitMovingPanel(movingPanel) SelectedPlayerEntry = nil inWaitForClick=false end) else --movingPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) SelectedPlayerEntry = entry SelectedPlayer = entry['Player'] entry['Frame'].BackgroundColor3 = Color3.new(0,1,1) entry['Frame'].BackgroundTransparency = .5 Spawn(function() TweenBackgroundTransparency(entry['Frame'],.5,1,1) end) Delay(1, function() if not InPopupWaitForClick then SelectedPlayerEntry = nil end end) StartDrag() end end --[[ the basic update for the playerlist mode's state, assures the order and length of the player frames --]] function PlayerListModeUpdate() RecreateScoreColumns(PlayerFrames) table.sort(PlayerFrames,PlayerSortFunction) for i,val in ipairs(PlayerFrames) do MiddleFrames[i] = val['Frame'] end for i = #PlayerFrames + 1,#MiddleFrames,1 do MiddleFrames[i] = nil end UpdateMinimize() end --[[ this one's a doozie, happens when a player is added to the game inits their player frame and player entry, assigns them to a team if possible, and hooks up their leaderstats @Args: nplayer new player object to insert --]] function InsertPlayerFrame(nplayer) while AddingFrameLock do debugprint('waiting to insert '..nplayer.Name) wait(1/30) end AddingFrameLock = true local nFrame = MiddleTemplate:Clone() WaitForChild(WaitForChild(nFrame,'TitleFrame'),'Title').Text = nplayer.Name nFrame.Position = UDim2.new(1,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0) local nfriendstatus = GetFriendStatus(nplayer) nFrame:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(nplayer.MembershipType,nplayer.Name) nFrame:FindFirstChild('FriendLabel').Image = getFriendStatusIcon(nfriendstatus) nFrame.Name = nplayer.Name WaitForChild(WaitForChild(nFrame,'TitleFrame'),'Title').Text = nplayer.Name --move for bc label nFrame.FriendLabel.Position=nFrame.FriendLabel.Position+UDim2.new(0,17,0,0) nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,17,0,0) if(nFrame:FindFirstChild('FriendLabel').Image ~= '') then nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,17,0,0) --nFrame.FriendLabel.Position=nFrame.TitleFrame.Position+UDim2.new(nFrame.TitleFrame.Size.X.Scale,-20+nFrame.TitleFrame.Size.X.Offset,0,0) end if nplayer.Name == LocalPlayer.Name then nFrame.TitleFrame.Title.Font = 'ArialBold' nFrame.PlayerScore.Font = 'ArialBold' ChangeHeaderName(nplayer.Name) local dropShadow = nFrame.TitleFrame.Title:Clone() dropShadow.TextColor3 = Color3.new(0,0,0) dropShadow.TextTransparency=0 dropShadow.ZIndex=2 dropShadow.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,1,0,1) dropShadow.Name='DropShadow' dropShadow.Parent= nFrame.TitleFrame elseif LocalPlayer:IsFriendsWith(nplayer.userId) then end nFrame.TitleFrame.Title.Font = 'ArialBold' nFrame.Parent = ListFrame nFrame:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0), "Out", "Quad", .5,true) UpdateMinimize() local nentry = {} nentry['Frame'] = nFrame nentry['Player'] = nplayer nentry['ID'] = AddId AddId = AddId + 1 table.insert(PlayerFrames,nentry) if #TeamFrames~=0 then if nplayer.Neutral then nentry['MyTeam'] = nil if not NeutralTeam then AddNeutralTeam() else AddPlayerToTeam(NeutralTeam,nentry) end else local addedToTeam=false for i,tval in ipairs(TeamFrames) do if tval['MyTeam'].TeamColor == nplayer.TeamColor then AddPlayerToTeam(tval,nentry) nentry['MyTeam'] = tval addedToTeam=true end end if not addedToTeam then nentry['MyTeam']=nil if not NeutralTeam then AddNeutralTeam() else AddPlayerToTeam(NeutralTeam,nentry) end nentry['MyTeam'] = NeutralTeam end end end if nplayer==LocalPlayer and nplayer:FindFirstChild('leaderstats') then LeaderstatsAdded(nentry) end nplayer.ChildAdded:connect(function(nchild) if nplayer==LocalPlayer and nchild.Name == 'leaderstats' then while AddingFrameLock do debugprint('in adding leaderstats lock') wait(1/30) end AddingFrameLock = true LeaderstatsAdded(nentry) AddingFrameLock = false end end) nplayer.ChildRemoved:connect(function (nchild) if nplayer==LocalPlayer and nchild.Name == 'leaderstats' then LeaderstatsRemoved(nchild,nentry) end end) nplayer.Changed:connect(function(prop)PlayerChanged(nentry,prop) end) local listener = WaitForChild(nFrame,'ClickListener') listener.Active = true listener.MouseButton1Down:connect(function() OnPlayerEntrySelect(nentry) end) AddMiddleBGFrame() BaseUpdate() AddingFrameLock = false end --[[ Note:major optimization can be done here removes this player's frame if it exists, calls base update --]] function RemovePlayerFrame(tplayer) while AddingFrameLock do debugprint('in removing player frame lock') wait(1/30) end AddingFrameLock = true local tteam for i,key in ipairs(PlayerFrames) do if tplayer == key['Player'] then if PopUpClipFrame.Parent == key['Frame'] then PopUpClipFrame.Parent = nil end key['Frame']:Destroy() tteam=key['MyTeam'] table.remove(PlayerFrames,i) end end if tteam then for j,tentry in ipairs(tteam['MyPlayers']) do if tentry['Player'] == tplayer then RemovePlayerFromTeam(tteam,j) end end end RemoveMiddleBGFrame() UpdateMinimize() BaseUpdate() AddingFrameLock = false end Players.ChildRemoved:connect(RemovePlayerFrame) ---------------------------- -- Team Callback Functions ---------------------------- --[[ turns a list of team entries with sub lists of players into a single ordered list, in the correct order,and of the correct length @Args: tframes the team entries to unroll outframes the list to unroll these entries into --]] function UnrollTeams(tframes,outframes) local numEntries = 0 if NeutralTeam and not NeutralTeam['IsHidden'] then for i,val in ipairs(NeutralTeam['MyPlayers']) do numEntries = numEntries + 1 outframes[numEntries] = val['Frame'] end numEntries = numEntries + 1 outframes[numEntries] = NeutralTeam['Frame'] end for i,val in ipairs(tframes) do if not val['IsHidden'] then for j,pval in ipairs(val.MyPlayers) do numEntries = numEntries + 1 outframes[numEntries] = pval['Frame'] end numEntries = numEntries + 1 outframes[numEntries] = val['Frame'] end end -- clear any additional entries from outframes for i = numEntries + 1,#outframes,1 do outframes[i] = nil end end --[[ uses lua's table.sort to sort the teams --]] function TeamSortFunc(a,b) if a['TeamScore'] == b['TeamScore'] then return a['ID'] < b['ID'] end if not a['TeamScore'] then return false end if not b['TeamScore'] then return true end return a['TeamScore'] < b['TeamScore'] end --[[ consider adding lock with wait for performance sorts each of the team's player lists induvidually, adds up the team scores. @Args: tentries table of team entries --]] function SortTeams(tentries) for i,val in ipairs(tentries) do table.sort(val['MyPlayers'],PlayerSortFunction) AddTeamScores(val) end table.sort(tentries,TeamSortFunc) end --[[ base update for team mode, adds up the scores of all teams, sorts them, then unrolls them into middleframes --]] function TeamListModeUpdate() RecreateScoreColumns(PlayerFrames) SortTeams(TeamFrames) if NeutralTeam then AddTeamScores(NeutralTeam) --RecreateScoreColumns(NeutralTeam['MyPlayers']) end UnrollTeams(TeamFrames,MiddleFrames) end --[[ adds up all the score of this team's players to form the team score @Args: team team entry to sum the scores of --]] function AddTeamScores(team) for j = 1, #ScoreNames,1 do local i = ScoreNames[j] local tscore = 0 for _,j in ipairs(team['MyPlayers']) do if j['Player']:FindFirstChild('leaderstats') and j['Player'].leaderstats:FindFirstChild(i['Name']) then tscore = tscore + GetScoreValue(j['Player'].leaderstats[i['Name']]) end end if team['Frame']:FindFirstChild(i['Name']) then team['Frame'][i['Name']].Size = UDim2.new(1 - (ScrollBarFrame.Size.X.Scale * 2),- ((j-1) * SpacingPerStat),TemplateFrameYSize,0) team['Frame'][i['Name']].Text = tostring(tscore) end end UpdateMinimize() end --[[ finds previous team this player was on, and if it exists calls removeplayerfromteam @Args entry Player entry --]] function FindRemovePlayerFromTeam(entry) if entry['MyTeam'] then for j,oldEntry in ipairs(entry['MyTeam']['MyPlayers']) do if oldEntry['Player'] == entry['Player'] then RemovePlayerFromTeam(entry['MyTeam'],j) return end end elseif NeutralTeam then for j,oldEntry in ipairs(NeutralTeam['MyPlayers']) do if oldEntry['Player'] == entry['Player'] then RemovePlayerFromTeam(NeutralTeam,j) return end end end end --[[ removes a single player from a given team (not usually called directly) @Args: teamEntry team entry to remove player from index index of player in 'MyPlayers' list to remove --]] function RemovePlayerFromTeam(teamEntry,index) table.remove(teamEntry['MyPlayers'],index) --if teamEntry['AutoHide'] and #teamEntry['MyPlayers'] == 0 then if teamEntry==NeutralTeam and #teamEntry['MyPlayers']==0 then RemoveNeutralTeam() end end --[[ adds player entry entry to teamentry removes them from any previous team @Args: teamEntry entry of team to add player to entry player entry to add to this team --]] function AddPlayerToTeam(teamEntry,entry) FindRemovePlayerFromTeam(entry) table.insert(teamEntry['MyPlayers'],entry) entry['MyTeam'] = teamEntry if teamEntry['IsHidden'] then teamEntry['Frame'].Parent = ListFrame AddMiddleBGFrame() end teamEntry['IsHidden'] = false end function SetPlayerToTeam(entry) FindRemovePlayerFromTeam(entry) -- check to see if team exists, if it does add to that team local setToTeam = false for i,tframe in ipairs(TeamFrames) do -- add my entry on the new team if tframe['MyTeam'].TeamColor == entry['Player'].TeamColor then AddPlayerToTeam(tframe,entry) setToTeam = true end end -- if player was set to an invalid team, then set it back to neutral if not setToTeam then entry['MyTeam']=nil if not NeutralTeam then AddNeutralTeam() else AddPlayerToTeam(NeutralTeam,entry) end end end --[[ Note:another big one, consiter breaking up called when any children of player changes handles 'Neutral', teamColor, Name and MembershipType changes @Args entry Player entry changed property name of property changed --]] function PlayerChanged(entry, property) while PlayerChangedLock do debugprint('in playerchanged lock') wait(1/30) end PlayerChangedLock=true if property == 'Neutral' then -- if player changing to neutral if entry['Player'].Neutral then debugprint(entry['Player'].Name..'setting to neutral') FindRemovePlayerFromTeam(entry) entry['MyTeam']=nil if not NeutralTeam then debugprint(entry['Player'].Name..'creating neutral team') AddNeutralTeam() else debugprint(entry['Player'].Name..'adding to neutral team') AddPlayerToTeam(NeutralTeam,entry) end else -- else player switching to a team, or a weird edgecase SetPlayerToTeam(entry) end elseif property == 'TeamColor' and not entry['Player'].Neutral and entry['Player'] ~= entry['MyTeam'] then debugprint(entry['Player'].Name..'setting to new team') SetPlayerToTeam(entry) elseif property == 'Name' or property == 'MembershipType' then entry['Frame']:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(entry['Player'].MembershipType,entry['Player'].Name) entry['Frame'].Name = entry['Player'].Name entry['Frame'].TitleFrame.Title.Text = entry['Player'].Name if(entry['Frame'].BCLabel.Image ~= '') then entry['Frame'].TitleFrame.Title.Position=UDim2.new(.01, 30, .1, 0) end if entry['Player'] == LocalPlayer then entry['Frame'].TitleFrame.DropShadow.Text= entry['Player'].Name ChangeHeaderName(entry['Player'].Name) end end BaseUpdate() PlayerChangedLock=false end function OnFriendshipChanged(player,friendStatus) for _, entry in ipairs(PlayerFrames) do if entry['Player']==player then local nicon = getFriendStatusIcon(friendStatus) if nicon == '' and entry['Frame'].FriendLabel.Image ~= '' then entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position-UDim2.new(0,17,0,0) elseif nicon ~= '' and entry['Frame'].FriendLabel.Image == '' then entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position+UDim2.new(0,17,0,0) end entry['Frame'].FriendLabel.Image = nicon return end end end LocalPlayer.FriendStatusChanged:connect(OnFriendshipChanged) --[[ adds a neutral team if nessisary Note: a lot of redundant code here, might want to refactor to share a function with insertteamframe --]] function AddNeutralTeam() while NeutralTeamLock do debugprint('in neutral team 2 lock') wait() end NeutralTeamLock = true local defaultTeam = Instance.new('Team') defaultTeam.TeamColor = BrickColor.new('White') defaultTeam.Name = 'Neutral' local nentry = {} nentry['MyTeam'] = defaultTeam nentry['MyPlayers'] = {} nentry['Frame'] = MiddleTemplate:Clone() WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = defaultTeam.Name nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0) nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0) --nentry['Frame'].TitleFrame.Title.TextScaled=true nentry['Frame'].TitleFrame.Title.Font = 'ArialBold' nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0) WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(StartDrag) nentry['Frame'].ClickListener.BackgroundColor3 = Color3.new(1,1,1) nentry['Frame'].ClickListener.BackgroundTransparency = .7 nentry['Frame'].ClickListener.AutoButtonColor=false nentry['AutoHide'] = true nentry['IsHidden'] = true for _,i in pairs(PlayerFrames) do if i['Player'].Neutral or not i['MyTeam'] then AddPlayerToTeam(nentry,i) end end if #nentry['MyPlayers'] > 0 then NeutralTeam = nentry UpdateMinimize() BaseUpdate() end NeutralTeamLock = false end function RemoveNeutralTeam() while NeutralTeamLock do debugprint('in neutral team lock') wait() end NeutralTeamLock = true NeutralTeam['Frame']:Destroy() NeutralTeam=nil RemoveMiddleBGFrame() NeutralTeamLock = false end --[[ --]] function TeamScoreChanged(entry,nscore) WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nscore) entry['TeamScore'] = nscore end --[[ called when child added to a team, used for autohide functionality Note: still has teamscore, consiter removing --]] function TeamChildAdded(entry,nchild) if nchild.Name == 'AutoHide' then entry['AutoHide'] = true elseif nchild.Name == 'TeamScore' then WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nchild.Value) entry['TeamScore'] = nchild.Value nchild.Changed:connect(function() TeamScoreChanged(entry,nchild.Value) end) end end --[[ called when child added to a team, used for autohide functionality Note: still has teamscore, consiter removing --]] function TeamChildRemoved(entry,nchild) if nchild.Name == 'AutoHide' then entry['AutoHide'] = false elseif nchild.Name == 'TeamScore' then WaitForChild(entry['Frame'],'PlayerScore').Text = "" entry['TeamScore'] = nil end end --[[ creates team entry and frame for this team, sets up listeners for this team adds any players intended for this team,Creates neutral team if this is the first team added Note:might be best to break this into multiple functions to simplify @Args: nteam new team object added --]] function InsertTeamFrame(nteam) while AddingFrameLock do debugprint('in adding team frame lock') wait(1/30) end AddingFrameLock = true local nentry = {} nentry['MyTeam'] = nteam nentry['MyPlayers'] = {} nentry['Frame'] = MiddleTemplate:Clone() WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = nteam.Name nentry['Frame'].TitleFrame.Title.Font = 'ArialBold' nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0) nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0) --nentry['Frame'].TitleFrame.Title.TextScaled=true nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0) WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(StartDrag) nentry['Frame'].ClickListener.BackgroundColor3 = nteam.TeamColor.Color nentry['Frame'].ClickListener.BackgroundTransparency = .7 nentry['Frame'].ClickListener.AutoButtonColor=false AddId = AddId + 1 nentry['ID'] = AddId nentry['AutoHide'] = false if nteam:FindFirstChild('AutoHide') then nentry['AutoHide'] = true end if nteam:FindFirstChild('TeamScore') then TeamChildAdded(nentry,nteam.TeamScore) end nteam.ChildAdded:connect(function(nchild) TeamChildAdded(nentry,nchild) end) nteam.ChildRemoved:connect(function(nchild) TeamChildRemoved(nentry,nchild) end) for _,i in pairs(PlayerFrames) do if not i['Player'].Neutral and i['Player'].TeamColor == nteam.TeamColor then AddPlayerToTeam(nentry,i) end end nentry['IsHidden'] = false if not nentry['AutoHide'] or #nentry['MyPlayers'] > 0 then nentry['Frame'].Parent = ListFrame nentry['Frame']:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0), "Out", "Quad", .5,true) AddMiddleBGFrame() else nentry['IsHidden'] = true nentry['Frame'].Parent = nil end table.insert(TeamFrames,nentry) UpdateMinimize() BaseUpdate() if #TeamFrames == 1 and not NeutralTeam then AddNeutralTeam() end AddingFrameLock = false end --[[ removes team from team list @Args: nteam Teamobject to remove --]] function RemoveTeamFrame(nteam) while AddingFrameLock do debugprint('in removing team frame lock') wait(1/30) end AddingFrameLock = true if IsMinimized.Value then -- ListFrame.Position = ListFrame.Position + UDim2.new(0,0,MiddleTemplate.Size.Y.Scale,0) end local myEntry for i,key in ipairs(TeamFrames) do if nteam == key['MyTeam'] then myEntry = key key['Frame']:Destroy() table.remove(TeamFrames,i) end end if #TeamFrames==0 then if NeutralTeam then RemoveNeutralTeam() end end for i,key in ipairs(myEntry['MyPlayers']) do RemovePlayerFromTeam(myEntry,i) PlayerChanged(key, 'TeamColor') end RemoveMiddleBGFrame() BaseUpdate() AddingFrameLock = false end function TeamAdded(nteam) InsertTeamFrame(nteam) end function TeamRemoved(nteam) RemoveTeamFrame(nteam) end --------------------------------- --[[ called when ANYTHING changes the state of the playerlist re-sorts everything,assures correct positions of all elements --]] function BaseUpdate() while BaseUpdateLock do debugprint('in baseupdate lock') wait(1/30) end BaseUpdateLock = true if #TeamFrames == 0 then PlayerListModeUpdate() else TeamListModeUpdate() end for i,key in ipairs(MiddleFrames) do if key.Parent ~= nil then key:TweenPosition(UDim2.new(.5,0,((#MiddleFrames - (i)) * key.Size.Y.Scale),0), "Out", "Quad", .9,true) end end if not IsMinimized.Value and #MiddleFrames>DefaultEntriesOnScreen then UpdateScrollPosition() end UpdateScrollBarVisibility() debugprint('EndBaseUpdate') BaseUpdateLock = false end --[[ code for attaching tab key to maximizing player list --]] game.GuiService:AddKey("\t") local LastTabTime = time() game.GuiService.KeyPressed:connect( function(key) if key == "\t" then debugprint('caught tab key') local modalCheck, isModal = pcall(function() return game.GuiService.IsModalDialog end) if modalCheck == false or (modalCheck and isModal == false) then if time() - LastTabTime > 0.4 then LastTabTime = time() if IsTabified.Value then if not IsMaximized.Value then ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Quad',1,true) IsMaximized.Value = true else ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Quad',1,true) IsMaximized.Value = false IsMinimized.Value=true end else ToggleMaximize() end end end end end) ---------------------------- -- Hookups and initialization ---------------------------- function debugPlayerAdd(p) InsertPlayerFrame(p) end while not game:GetService('Teams') do wait(1/30) debugprint('Waiting For Teams') end for _,i in pairs(game.Teams:GetTeams()) do TeamAdded(i) end for _,i in pairs(Players:GetPlayers()) do Spawn(function() debugPlayerAdd(i) end) end--InsertPlayerFrame(i) end game.Teams.ChildAdded:connect(TeamAdded) game.Teams.ChildRemoved:connect(TeamRemoved) Players.ChildAdded:connect(function(tplayer) Spawn(function() debugPlayerAdd(tplayer) end) end)--InsertPlayerFrame) InitReportAbuse() BaseUpdate() --UGGGLY,find a better way later wait(2) IsPersonalServer= not not game.Workspace:FindFirstChild("PSVariable") ---------------------------- -- Running Logic ---------------------------- --debug stuffs, will only run for 'newplayerlistisbad' --REMOVEME if LocalPlayer.Name == 'newplayerlistisbad' then debugFrame.Parent = ScreenGui Spawn(function() while true do local str_players='' for _,i in pairs(game.Players:GetPlayers()) do str_players= str_players .." " .. i.Name end debugplayers.Text=str_players wait(.5) end end) end function EnsureValidity() while true do --make sure all players are in the player list --and make sure there are no entries that corespond to non-existant players local unfoundEntries={} for k,v in pairs(PlayerFrames) do unfoundEntries[k] = v end --for all players for _,i in pairs(Players:GetPlayers()) do local foundPlayer=false --for all known players for entryIndex,j in pairs(PlayerFrames) do -- if I know about this player, tag it if i==j['Player'] then foundPlayer=true unfoundEntries[entryIndex]=nil end end --if this player is not known if not foundPlayer then wait(.5) --do a double check for _,j in pairs(PlayerFrames) do if i==j['Player'] then foundPlayer=true end end if not foundPlayer then InsertPlayerFrame(i) debugOutput.Text= "Manual Insertion! " .. i.Name end end end --for any additional entries, never found, remove them for _,j in pairs(unfoundEntries) do RemovePlayerFrame(j['Player']) debugOutput.Text= "Player Manual Removal! " ..j['Player'].Name end wait(1/30) --make sure there are no gaps or overlaps in the playerlist while GetEntryListLength()>#MiddleFrameBackgrounds do AddMiddleBGFrame() end while GetEntryListLength()<#MiddleFrameBackgrounds do RemoveMiddleBGFrame() end wait(1/30) --remove neutral team if it shouldn't exist if NeutralTeam and (#NeutralTeam['MyPlayers']==0 or #TeamFrames==0) then wait(.5) if NeutralTeam and (#NeutralTeam['MyPlayers']==0 or #TeamFrames==0) then RemoveNeutralTeam() debugOutput.Text= "Manual removal of neutral team! " end end wait(1/30) --do a base update, just ot be sure BaseUpdate() wait(1/30) end end --quick fix running logic, PLEASE LET ME REPLACE LATER --Spawn(EnsureValidity) true TimeoutScript wait(5) local dialog = script.Parent if dialog:IsA("Dialog") then dialog.InUse = false end script:Remove() false ResetCommand function onChatted(msg, speaker) source = string.lower(speaker.Name) msg = string.lower(msg) -- Note: This one is NOT caps sensitive if msg == "!!!reset" then speaker.Character.Humanoid.Health = 0 end end function onPlayerEntered(newPlayer) newPlayer.Chatted:connect(function(msg) onChatted(msg, newPlayer) end) end game.Players.ChildAdded:connect(onPlayerEntered) true ReenableDialogScript wait(5) local dialog = script.Parent if dialog:IsA("Dialog") then dialog.InUse = false end script:Remove() Chat false ChatScript --rbxsig%JEfYnuC18EOdJ5gffQHlphGalfinD7ZNa+lFyYhYGQmQKlc/17N4PkAlQOjn7p5BdnyvBX3SUw7sweW90l/eUVzzt3dV/Vm63x6KIHjG8HLPwkxKCrtLbV4Mnw5q6mIS1A3GYXDkd3HG5iKgRfQHlCaCut4VQXquAtSITfkUJhc=% --rbxassetid%60595411% local t = {} --JSON Encoder and Parser for Lua 5.1 -- --Copyright 2007 Shaun Brown (http://www.chipmunkav.com) --All Rights Reserved. --Permission is hereby granted, free of charge, to any person --obtaining a copy of this software to deal in the Software without --restriction, including without limitation the rights to use, --copy, modify, merge, publish, distribute, sublicense, and/or --sell copies of the Software, and to permit persons to whom the --Software is furnished to do so, subject to the following conditions: --The above copyright notice and this permission notice shall be --included in all copies or substantial portions of the Software. --If you find this software useful please give www.chipmunkav.com a mention. --THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, --EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES --OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. --IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR --ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF --CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN --CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. local string = string local math = math local table = table local error = error local tonumber = tonumber local tostring = tostring local type = type local setmetatable = setmetatable local pairs = pairs local ipairs = ipairs local assert = assert local Chipmunk = Chipmunk local StringBuilder = { buffer = {} } function StringBuilder:New() local o = {} setmetatable(o, self) self.__index = self o.buffer = {} return o end function StringBuilder:Append(s) self.buffer[#self.buffer+1] = s end function StringBuilder:ToString() return table.concat(self.buffer) end local JsonWriter = { backslashes = { ['\b'] = "\\b", ['\t'] = "\\t", ['\n'] = "\\n", ['\f'] = "\\f", ['\r'] = "\\r", ['"'] = "\\\"", ['\\'] = "\\\\", ['/'] = "\\/" } } function JsonWriter:New() local o = {} o.writer = StringBuilder:New() setmetatable(o, self) self.__index = self return o end function JsonWriter:Append(s) self.writer:Append(s) end function JsonWriter:ToString() return self.writer:ToString() end function JsonWriter:Write(o) local t = type(o) if t == "nil" then self:WriteNil() elseif t == "boolean" then self:WriteString(o) elseif t == "number" then self:WriteString(o) elseif t == "string" then self:ParseString(o) elseif t == "table" then self:WriteTable(o) elseif t == "function" then self:WriteFunction(o) elseif t == "thread" then self:WriteError(o) elseif t == "userdata" then self:WriteError(o) end end function JsonWriter:WriteNil() self:Append("null") end function JsonWriter:WriteString(o) self:Append(tostring(o)) end function JsonWriter:ParseString(s) self:Append('"') self:Append(string.gsub(s, "[%z%c\\\"/]", function(n) local c = self.backslashes[n] if c then return c end return string.format("\\u%.4X", string.byte(n)) end)) self:Append('"') end function JsonWriter:IsArray(t) local count = 0 local isindex = function(k) if type(k) == "number" and k > 0 then if math.floor(k) == k then return true end end return false end for k,v in pairs(t) do if not isindex(k) then return false, '{', '}' else count = math.max(count, k) end end return true, '[', ']', count end function JsonWriter:WriteTable(t) local ba, st, et, n = self:IsArray(t) self:Append(st) if ba then for i = 1, n do self:Write(t[i]) if i < n then self:Append(',') end end else local first = true; for k, v in pairs(t) do if not first then self:Append(',') end first = false; self:ParseString(k) self:Append(':') self:Write(v) end end self:Append(et) end function JsonWriter:WriteError(o) error(string.format( "Encoding of %s unsupported", tostring(o))) end function JsonWriter:WriteFunction(o) if o == Null then self:WriteNil() else self:WriteError(o) end end local StringReader = { s = "", i = 0 } function StringReader:New(s) local o = {} setmetatable(o, self) self.__index = self o.s = s or o.s return o end function StringReader:Peek() local i = self.i + 1 if i <= #self.s then return string.sub(self.s, i, i) end return nil end function StringReader:Next() self.i = self.i+1 if self.i <= #self.s then return string.sub(self.s, self.i, self.i) end return nil end function StringReader:All() return self.s end local JsonReader = { escapes = { ['t'] = '\t', ['n'] = '\n', ['f'] = '\f', ['r'] = '\r', ['b'] = '\b', } } function JsonReader:New(s) local o = {} o.reader = StringReader:New(s) setmetatable(o, self) self.__index = self return o; end function JsonReader:Read() self:SkipWhiteSpace() local peek = self:Peek() if peek == nil then error(string.format( "Nil string: '%s'", self:All())) elseif peek == '{' then return self:ReadObject() elseif peek == '[' then return self:ReadArray() elseif peek == '"' then return self:ReadString() elseif string.find(peek, "[%+%-%d]") then return self:ReadNumber() elseif peek == 't' then return self:ReadTrue() elseif peek == 'f' then return self:ReadFalse() elseif peek == 'n' then return self:ReadNull() elseif peek == '/' then self:ReadComment() return self:Read() else return nil end end function JsonReader:ReadTrue() self:TestReservedWord{'t','r','u','e'} return true end function JsonReader:ReadFalse() self:TestReservedWord{'f','a','l','s','e'} return false end function JsonReader:ReadNull() self:TestReservedWord{'n','u','l','l'} return nil end function JsonReader:TestReservedWord(t) for i, v in ipairs(t) do if self:Next() ~= v then error(string.format( "Error reading '%s': %s", table.concat(t), self:All())) end end end function JsonReader:ReadNumber() local result = self:Next() local peek = self:Peek() while peek ~= nil and string.find( peek, "[%+%-%d%.eE]") do result = result .. self:Next() peek = self:Peek() end result = tonumber(result) if result == nil then error(string.format( "Invalid number: '%s'", result)) else return result end end function JsonReader:ReadString() local result = "" assert(self:Next() == '"') while self:Peek() ~= '"' do local ch = self:Next() if ch == '\\' then ch = self:Next() if self.escapes[ch] then ch = self.escapes[ch] end end result = result .. ch end assert(self:Next() == '"') local fromunicode = function(m) return string.char(tonumber(m, 16)) end return string.gsub( result, "u%x%x(%x%x)", fromunicode) end function JsonReader:ReadComment() assert(self:Next() == '/') local second = self:Next() if second == '/' then self:ReadSingleLineComment() elseif second == '*' then self:ReadBlockComment() else error(string.format( "Invalid comment: %s", self:All())) end end function JsonReader:ReadBlockComment() local done = false while not done do local ch = self:Next() if ch == '*' and self:Peek() == '/' then done = true end if not done and ch == '/' and self:Peek() == "*" then error(string.format( "Invalid comment: %s, '/*' illegal.", self:All())) end end self:Next() end function JsonReader:ReadSingleLineComment() local ch = self:Next() while ch ~= '\r' and ch ~= '\n' do ch = self:Next() end end function JsonReader:ReadArray() local result = {} assert(self:Next() == '[') local done = false if self:Peek() == ']' then done = true; end while not done do local item = self:Read() result[#result+1] = item self:SkipWhiteSpace() if self:Peek() == ']' then done = true end if not done then local ch = self:Next() if ch ~= ',' then error(string.format( "Invalid array: '%s' due to: '%s'", self:All(), ch)) end end end assert(']' == self:Next()) return result end function JsonReader:ReadObject() local result = {} assert(self:Next() == '{') local done = false if self:Peek() == '}' then done = true end while not done do local key = self:Read() if type(key) ~= "string" then error(string.format( "Invalid non-string object key: %s", key)) end self:SkipWhiteSpace() local ch = self:Next() if ch ~= ':' then error(string.format( "Invalid object: '%s' due to: '%s'", self:All(), ch)) end self:SkipWhiteSpace() local val = self:Read() result[key] = val self:SkipWhiteSpace() if self:Peek() == '}' then done = true end if not done then ch = self:Next() if ch ~= ',' then error(string.format( "Invalid array: '%s' near: '%s'", self:All(), ch)) end end end assert(self:Next() == "}") return result end function JsonReader:SkipWhiteSpace() local p = self:Peek() while p ~= nil and string.find(p, "[%s/]") do if p == '/' then self:ReadComment() else self:Next() end p = self:Peek() end end function JsonReader:Peek() return self.reader:Peek() end function JsonReader:Next() return self.reader:Next() end function JsonReader:All() return self.reader:All() end function Encode(o) local writer = JsonWriter:New() writer:Write(o) return writer:ToString() end function Decode(s) local reader = JsonReader:New(s) return reader:Read() end function Null() return Null end -------------------- End JSON Parser ------------------------ t.DecodeJSON = function(jsonString) if type(jsonString) == "string" then return Decode(jsonString) end print("RbxUtil.DecodeJSON expects string argument!") return nil end t.EncodeJSON = function(jsonTable) return Encode(jsonTable) end ------------------------------Terrain Utilities Begin-------------------------------- --makes a wedge at location x, y, z --sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was --returns true if made a wedge, false if the cell remains a block t.MakeWedge = function(x, y, z, defaultmaterial) local c = game:GetService("TerrainService") --gather info about all the cells around x, y, z surroundings = {} --surroundings is a 3 x 3 x 3 array of the material of the cells adjacent to x, y, z for i = x - 1, x + 1 do surroundings[i] = {} for j = y - 1, y + 1 do surroundings[i][j] = {} for k = z - 1, z + 1 do print("seeing the latest") local material = nil local wedge = nil local rotation = nil material, wedge, rotation = c:GetCellFull(i, j, k) surroundings[i][j][k] = material end end end --make some useful arrays and counters local sides = {} --sides is an array of the material of the 4 adjacent sides sides[0] = surroundings[x - 1][y][z] sides[1] = surroundings[x][y][z + 1] sides[2] = surroundings[x + 1][y][z] sides[3] = surroundings[x][y][z - 1] local adjacentSides = 0 for n = 0, 3 do if sides[n] > 0 then adjacentSides = adjacentSides + 1 end end local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above sidesAbove[0] = surroundings[x - 1][y + 1][z] sidesAbove[1] = surroundings[x][y + 1][z + 1] sidesAbove[2] = surroundings[x + 1][y + 1][z] sidesAbove[3] = surroundings[x][y + 1][z - 1] local adjacentSidesAbove = 0 for n = 0, 3 do if sidesAbove[n] > 0 then adjacentSidesAbove = adjacentSidesAbove + 1 end end local corners = {} --corners is an array of the material of the 4 adjacent corners corners[0] = surroundings[x - 1][y][z - 1] corners[1] = surroundings[x - 1][y][z + 1] corners[2] = surroundings[x + 1][y][z + 1] corners[3] = surroundings[x + 1][y][z - 1] local adjacentCorners = 0 for n = 0, 3 do if corners[n] > 0 then adjacentCorners = adjacentCorners + 1 end end local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above cornersAbove[0] = surroundings[x - 1][y + 1][z - 1] cornersAbove[1] = surroundings[x - 1][y + 1][z + 1] cornersAbove[2] = surroundings[x + 1][y + 1][z + 1] cornersAbove[3] = surroundings[x + 1][y + 1][z - 1] local adjacentCornersAbove = 0 for n = 0, 3 do if cornersAbove[n] > 0 then adjacentCornersAbove = adjacentCornersAbove + 1 end end --determine what type of wedge to make local material = nil local wedge = nil local rotation = nil if defaultmaterial then material = defaultmaterial else material, wedge, rotation = c:GetCellFull(x, y, z) --start with the existing material, wedge, and rotation end wedge = 0 --default wedge is a block rotation = 0 --default rotation is 0 --type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then if adjacentSides == 1 then for n = 0, 3 do if sides[n] > 0 then wedge = 1 rotation = (n + 1) % 4 c:SetCellFull(x, y, z, material, wedge, rotation) return true end end elseif adjacentSides == 3 then for n = 0, 3 do if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then wedge = 1 rotation = (n + 2) % 4 c:SetCellFull(x, y, z, material, wedge, rotation) return true end end end end --type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner) if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then for n = 0, 3 do if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then wedge = 2 rotation = (n + 2) % 4 c:SetCellFull(x, y, z, material, wedge, rotation) return true end end end --type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then if adjacentCorners > 1 then for n = 0, 3 do if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then wedge = 3 rotation = (n + 3) % 4 c:SetCellFull(x, y, z, material, wedge, rotation) return true end end end elseif adjacentSides == 4 and adjacentCorners == 3 then for n = 0, 3 do if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then wedge = 3 rotation = (n + 3) % 4 c:SetCellFull(x, y, z, material, wedge, rotation) return true end end end --type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides if adjacentSides == 2 and adjacentCorners < 4 then for n = 0, 3 do if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then wedge = 4 rotation = n c:SetCellFull(x, y, z, material, wedge, rotation) return true end end end c:SetCellFull(x, y, z, material, wedge, rotation) return false end -----------------------------Terrain Utilities End----------------------------- t.Help = function(funcNameOrFunc) --input argument can be a string or a function. Should return a description (of arguments and expected side effects) if funcNameOrFunc == "DecodeJSON" or funcNameOrFunc == t.DecodeJSON then return "Function DecodeJSON. " .. "Arguments: (string). " .. "Side effect: returns a table with all parsed JSON values" end if funcNameOrFunc == "EncodeJSON" or funcNameOrFunc == t.EncodeJSON then return "Function EncodeJSON. " .. "Arguments: (table). " .. "Side effect: returns a string composed of argument table in JSON data format" end if funcNameOrFunc == "MakeWedge" or funcNameOrFunc == t.MakeWedge then return "Function MakeWedge. " .. "Arguments: (x, y, z, [default material]). " .. "Description: Makes a wedge at location x, y, z. Sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was. Returns true if made a wedge, false if the cell remains a block " end end --rbxsig%REvu/wlKsFpV+wGhx4ZIeoKQ3ajJIMa8dt7TmxHPEQ3UyELsZVYT0DQiFiH7ICCEoiF9Yj9pNuB6DvyP739SU78jRrPa3Ln1aJHwdBur+X9TWjVvHDiHrezRhmWvXOIBhmw+/xoj+88xIoZABu36+kLyoHQDBbg8qrTf0CUZv5c=% --rbxassetid%97188756% --[[ //FileName: ChatScript.LUA //Written by: Sorcus //Description: Code for lua side chat on ROBLOX. Supports Scrolling. //NOTE: If you find any bugs or inaccuracies PM Sorcus on ROBLOX or @Canavus on Twitter ]] -- Utility functions + Globals local function WaitForChild(parent, childName) while parent:FindFirstChild(childName) == nil do parent.ChildAdded:wait(0.03) end return parent[childName] end function Create(guiType) return function(data) local obj = Instance.new(guiType) for k, v in pairs(data) do if type(k) == 'number' then v.Parent = obj else obj[k] = v end end return obj end end local function typedef(obj) return obj end local function IsPhone() end -- Users can use enough white spaces to spoof chatting as other players -- This function removes trailing and leading white spaces -- AFAIK, there is no reason for spam white spaces local function StringTrim(str) -- %S is whitespaces -- When we find the first non space character defined by ^%s -- we yank out anything in between that and the end of the string -- Everything else is replaced with %1 which is essentially nothing return (str:gsub("^%s*(.-)%s*$", "%1")) end while Game.Players.LocalPlayer == nil do wait(0.03) end local Player = Game.Players.LocalPlayer while Player.Character == nil do wait(0.03) end local RbxUtility = t local Gui = typedef(RbxUtility) local Camera = Game.Workspace.CurrentCamera -- Services local CoreGuiService = Game:GetService('CoreGui') local PlayersService = Game:GetService('Players') local DebrisService= Game:GetService('Debris') local GuiService = Game:GetService('GuiService') -- Lua Enums local Enums do Enums = {} local EnumName = {} -- used as unique key for enum name local enum_mt = { __call = function(self,value) return self[value] or self[tonumber(value)] end; __index = { GetEnumItems = function(self) local t = {} for i,item in pairs(self) do if type(i) == 'number' then t[#t+1] = item end end table.sort(t,function(a,b) return a.Value < b.Value end) return t end; }; __tostring = function(self) return "Enum." .. self[EnumName] end; } local item_mt = { __call = function(self,value) return value == self or value == self.Name or value == self.Value end; __tostring = function(self) return "Enum." .. self[EnumName] .. "." .. self.Name end; } function CreateEnum(enumName) return function(t) local e = {[EnumName] = enumName} for i,name in pairs(t) do local item = setmetatable({Name=name,Value=i,Enum=e,[EnumName]=enumName},item_mt) e[i] = item e[name] = item e[item] = item end Enums[enumName] = e return setmetatable(e, enum_mt) end end end --------------------------------------------------- ------------------ Input class -------------------- local Input = { Mouse = Player:GetMouse(), Speed = 0, Simulating = false, Configuration = { DefaultSpeed = 1 }, UserIsScrolling = false } --------------------------------------------------- ------------------ Chat class -------------------- local Chat = { ChatColors = { BrickColor.new("Bright red"), BrickColor.new("Bright blue"), BrickColor.new("Earth green"), BrickColor.new("Bright violet"), BrickColor.new("Bright orange"), BrickColor.new("Bright yellow"), BrickColor.new("Light reddish violet"), BrickColor.new("Brick yellow"), }, Gui = nil, Frame = nil, RenderFrame = nil, TapToChatLabel = nil, ClickToChatButton = nil, ScrollingLock = false, EventListener = nil, -- This is actually a ring buffer -- Meaning at hitting the historyLength it wraps around -- Reuses the text objects, so chat atmost uses 100 text objects MessageQueue = {}, -- Stores all the values for configuring chat Configuration = { FontSize = Enum.FontSize.Size12, -- 10 is good -- Also change this when you are changing the above, this is suboptimal but so is our interface to find FontSize NumFontSize = 12, HistoryLength = 20, -- stores up to 50 of the last chat messages for you to scroll through, Size = UDim2.new(0.38, 0, 0.20, 0), MessageColor = Color3.new(1, 1, 1), AdminMessageColor = Color3.new(1, 215/255, 0), XScale = 0.025, LifeTime = 45, Position = UDim2.new(0, 2, 0.05, 0), DefaultTweenSpeed = 0.15, }, -- This could be redone by just using the previous and next fields of the Queue -- But the iterators cause issues, will be optimized later SlotPositions_List = {}, -- To precompute and store all player null strings since its an expensive process CachedSpaceStrings_List = {}, MouseOnFrame = false, GotFocus = false, Messages_List = {}, MessageThread = nil, -- changing anything here might and WILL get you banned. - iagoMAO -- Admins_List = {'iagoMAO', 'Carrot', 'winsupermario1234', 'Bitl', 'QuackIAttack', 'khanglegos', 'Nukley', 'OliverA', 'Raymonf', 'coke', 'TheLivingBee', 'Peridorky', 'romulo27', 'robloxtester', 'CPunch', 'connor' }, SafeChat_List = { ['Use the Chat menu to talk to me.'] = {'/sc 0', true}, ['I can only see menu chats.'] = {'/sc 1', true}, ['Hello'] = { ['Hi'] = {'/sc 2_0', true, ['Hi there!'] = true, ['Hi everyone'] = true}, ['Howdy'] = {'/sc 2_1', true, ['Howdy partner!'] = true}, ['Greetings'] = {'/sc 2_2', true, ['Greetings everyone'] = true, ['Greetings Robloxians!'] = true, ['Seasons greetings!'] = true}, ['Welcome'] = {'/sc 2_3', true, ['Welcome to my place'] = true, ['Welcome to my barbeque'] = true, ['Welcome to our base'] = true}, ['Hey there!'] = {'/sc 2_4', true}, ['What\'s up?'] = {'/sc 2_5', true, ['How are you doing?'] = true, ['How\'s it going?'] = true, ['What\'s new?'] = true}, ['Good day'] = {'/sc 2_6', true, ['Good morning'] = true, ['Good evening'] = true, ['Good afternoon'] = true, ['Good night'] = true}, ['Silly'] = {'/sc 2_7', true, ['Waaaaaaaz up?!'] = true, ['Hullo!'] = true, ['Behold greatness, mortals!'] = true, ['Pardon me, is this Sparta?'] = true, ['THIS IS SPARTAAAA!'] = true}, ['Happy Holidays!'] = {'/sc 2_8', true, ['Happy New Year!'] = true, ['Happy Valentine\'s Day!'] = true, ['Beware the Ides of March!'] = true, ['Happy St. Patrick\'s Day!'] = true, ['Happy Easter!'] = true, ['Happy Earth Day!'] = true, ['Happy 4th of July!'] = true, ['Happy Thanksgiving!'] = true, ['Happy Halloween!'] = true, ['Happy Hanukkah!'] = true, ['Merry Christmas!'] = true, ['Happy Halloween!'] = true, ['Happy Earth Day!'] = true, ['Happy May Day!'] = true, ['Happy Towel Day!'] = true, ['Happy ROBLOX Day!'] = true, ['Happy LOL Day!'] = true }, [1] = '/sc 2' }, ['Goodbye'] = { ['Good Night']= {'/sc 3_0', true, ['Sweet dreams'] = true, ['Go to sleep!'] = true, ['Lights out!'] = true, ['Bedtime'] = true, ['Going to bed now'] = true}, ['Later']= {'/sc 3_1', true, ['See ya later'] = true, ['Later gator!'] = true, ['See you tomorrow'] = true}, ['Bye'] = {'/sc 3_2', true, ['Hasta la bye bye!'] = true}, ['I\'ll be right back'] = {'/sc 3_3', true}, ['I have to go'] = {'/sc 3_4', true}, ['Farewell'] = {'/sc 3_5', true, ['Take care'] = true, ['Have a nice day'] = true, ['Goodluck!'] = true, ['Ta-ta for now!'] = true}, ['Peace'] = {'/sc 3_6', true, ['Peace out!'] = true, ['Peace dudes!'] = true, ['Rest in pieces!'] = true}, ['Silly'] = {'/sc 3_7', true, ['To the batcave!'] = true, ['Over and out!'] = true, ['Happy trails!'] = true, ['I\'ve got to book it!'] = true, ['Tootles!'] = true, ['Smell you later!'] = true, ['GG!'] = true, ['My house is on fire! gtg.'] = true}, [1] = '/sc 3' }, ['Friend'] ={ ['Wanna be friends?'] = {'/sc 4_0', true}, ['Follow me'] = {'/sc 4_1', true, ['Come to my place!'] = true, ['Come to my base!'] = true, ['Follow me, team!'] = true, ['Follow me'] = true}, ['Your place is cool'] = {'/sc 4_2', true, ['Your place is fun'] = true, ['Your place is awesome'] = true, ['Your place looks good'] = true, ['This place is awesome!'] = true}, ['Thank you'] = {'/sc 4_3', true, ['Thanks for playing'] = true, ['Thanks for visiting'] = true, ['Thanks for everything'] = true, ['No, thank you'] = true, ['Thanx'] = true}, ['No problem'] = {'/sc 4_4', true, ['Don\'t worry'] = true, ['That\'s ok'] = true, ['np'] = true}, ['You are ...'] = {'/sc 4_5', true, ['You are great!'] = true, ['You are good!'] = true, ['You are cool!'] = true, ['You are funny!'] = true, ['You are silly!'] = true, ['You are awesome!'] = true, ['You are doing something I don\'t like, please stop'] = true }, ['I like ...'] = {'/sc 4_6', true, ['I like your name'] = true, ['I like your shirt'] = true, ['I like your place'] = true, ['I like your style'] = true, ['I like you'] = true, ['I like items'] = true, ['I like money'] = true}, ['Sorry'] = {'/sc 4_7', true, ['My bad!'] = true, ['I\'m sorry'] = true, ['Whoops!'] = true, ['Please forgive me.'] = true, ['I forgive you.'] = true, ['I didn\'t mean to do that.'] = true, ['Sorry, I\'ll stop now.'] = true}, [1] = '/sc 4' }, ['Questions'] = { ['Who?'] = {'/sc 5_0', true, ['Who wants to be my friend?'] = true, ['Who wants to be on my team?'] = true, ['Who made this brilliant game?'] = true}, ['What?'] = {'/sc 5_1', true, ['What is your favorite animal?'] = true, ['What is your favorite game?'] = true, ['What is your favorite movie?'] = true, ['What is your favorite TV show?'] = true, ['What is your favorite music?'] = true, ['What are your hobbies?'] = true, ['LOLWUT?'] = true}, ['When?'] = {'/sc 5_2', true, ['When are you online?'] = true, ['When is the new version coming out?'] = true, ['When can we play again?'] = true, ['When will your place be done?'] = true}, ['Where?'] = {'/sc 5_3', true, ['Where do you want to go?'] = true, ['Where are you going?'] = true, ['Where am I?!'] = true, ['Where did you go?'] = true}, ['How?'] = {'/sc 5_4', true, ['How are you today?'] = true, ['How did you make this cool place?'] = true, ['LOLHOW?'] = true}, ['Can I...'] = {'/sc 5_5', true, ['Can I have a tour?'] = true, ['Can I be on your team?'] = true, ['Can I be your friend?'] = true, ['Can I try something?'] = true, ['Can I have that please?'] = true, ['Can I have that back please?'] = true, ['Can I have borrow your hat?'] = true, ['Can I have borrow your gear?'] = true}, [1] = '/sc 5' }, ['Answers'] = { ['You need help?'] = {'/sc 6_0', true, ['Check out the news section'] = true, ['Check out the help section'] = true, ['Read the wiki!'] = true, ['All the answers are in the wiki!'] = true, ['I will help you with this.'] = true}, ['Some people ...'] = {'/sc 6_1', true, ['Me'] = true, ['Not me'] = true, ['You'] = true, ['All of us'] = true, ['Everyone but you'] = true, ['Builderman!'] = true, ['Telamon!'] = true, ['My team'] = true, ['My group'] = true, ['Mom'] = true, ['Dad'] = true, ['Sister'] = true, ['Brother'] = true, ['Cousin'] = true, ['Grandparent'] = true, ['Friend'] = true}, ['Time ...'] = {'/sc 6_2', true, ['In the morning'] = true, ['In the afternoon'] = true, ['At night'] = true, ['Tomorrow'] = true, ['This week'] = true, ['This month'] = true, ['Sometime'] = true, ['Sometimes'] = true, ['Whenever you want'] = true, ['Never'] = true, ['After this'] = true, ['In 10 minutes'] = true, ['In a couple hours'] = true, ['In a couple days'] = true}, ['Animals'] = {'/sc 6_3', true, ['Cats'] = {['Lion'] = true, ['Tiger'] = true, ['Leopard'] = true, ['Cheetah'] = true}, ['Dogs'] = {['Wolves'] = true, ['Beagle'] = true, ['Collie'] = true, ['Dalmatian'] = true, ['Poodle'] = true, ['Spaniel'] = true, ['Shepherd'] = true, ['Terrier'] = true, ['Retriever'] = true}, ['Horses'] = {['Ponies'] = true, ['Stallions'] = true, ['Pwnyz'] = true}, ['Reptiles'] = {['Dinosaurs'] = true, ['Lizards'] = true, ['Snakes'] = true, ['Turtles!'] = true}, ['Hamster'] = true, ['Monkey'] = true, ['Bears'] = true, ['Fish'] = {['Goldfish'] = true, ['Sharks'] = true, ['Sea Bass'] = true, ['Halibut'] = true, ['Tropical Fish'] = true}, ['Birds'] = {['Eagles'] = true, ['Penguins'] = true, ['Parakeets'] = true, ['Owls'] = true, ['Hawks'] = true, ['Pidgeons'] = true}, ['Elephants'] = true, ['Mythical Beasts'] = {['Dragons'] = true, ['Unicorns'] = true, ['Sea Serpents'] = true, ['Sphinx'] = true, ['Cyclops'] = true, ['Minotaurs'] = true, ['Goblins'] = true, ['Honest Politicians'] = true, ['Ghosts'] = true, ['Scylla and Charybdis'] = true} }, ['Games'] = {'/sc 6_4', true, ['Action'] = true, ['Puzzle'] = true, ['Strategy'] = true, ['Racing'] = true, ['RPG'] = true, ['Obstacle Course'] = true, ['Tycoon'] = true, ['Roblox'] = { ['BrickBattle'] = true, ['Community Building'] = true, ['Roblox Minigames'] = true, ['Contest Place'] = true}, ['Board games'] = { ['Chess'] = true, ['Checkers'] = true, ['Settlers of Catan'] = true, ['Tigris and Euphrates'] = true, ['El Grande'] = true, ['Stratego'] = true, ['Carcassonne'] = true} }, ['Sports'] = {'/sc 6_5', true, ['Hockey'] = true, ['Soccer'] = true, ['Football'] = true, ['Baseball'] = true, ['Basketball'] = true, ['Volleyball'] = true, ['Tennis'] = true, ['Sports team practice'] = true, ['Watersports'] = { ['Surfing'] = true,['Swimming'] = true, ['Water Polo'] = true}, ['Winter sports'] = { ['Skiing'] = true, ['Snowboarding'] = true, ['Sledding'] = true, ['Skating'] = true}, ['Adventure'] = {['Rock climbing'] = true, ['Hiking'] = true, ['Fishing'] = true, ['Horseback riding'] = true}, ['Wacky'] = {['Foosball'] = true, ['Calvinball'] = true, ['Croquet'] = true, ['Cricket'] = true, ['Dodgeball'] = true, ['Squash'] = true, ['Trampoline'] = true} }, ['Movies/TV'] = {'/sc 6_6', true, ['Science Fiction'] = true, ['Animated'] = {['Anime'] = true}, ['Comedy'] = true, ['Romantic'] = true, ['Action'] = true, ['Fantasy'] = true}, ['Music'] = {'/sc 6_7', true, ['Country'] = true, ['Jazz'] = true, ['Rap'] = true, ['Hip-hop'] = true, ['Techno'] = true, ['Classical'] = true, ['Pop'] = true, ['Rock'] = true}, ['Hobbies'] = {'/sc 6_8', true, ['Computers'] = { ['Building computers'] = true, ['Videogames'] = true, ['Coding'] = true, ['Hacking'] = true}, ['The Internet'] = { ['lol. teh internets!'] = true, ['Watching vids'] = true}, ['Dance'] = true, ['Gymnastics'] = true, ['Listening to music'] = true, ['Arts and crafts'] = true, ['Martial Arts'] = {['Karate'] = true, ['Judo'] = true, ['Taikwon Do'] = true, ['Wushu'] = true, ['Street fighting'] = true}, ['Music lessons'] = {['Playing in my band'] = true, ['Playing piano'] = true, ['Playing guitar'] = true, ['Playing violin'] = true, ['Playing drums'] = true, ['Playing a weird instrument'] = true} }, ['Location'] = {'/sc 6_9', true, ['USA'] = { ['West'] = { ['Alaska'] = true, ['Arizona'] = true, ['California'] = true, ['Colorado'] = true, ['Hawaii'] = true, ['Idaho'] = true, ['Montana'] = true, ['Nevada'] = true, ['New Mexico'] = true, ['Oregon'] = true, ['Utah'] = true, ['Washington'] = true, ['Wyoming'] = true }, ['South'] = { ['Alabama'] = true, ['Arkansas'] = true, ['Florida'] = true, ['Georgia'] = true, ['Kentucky'] = true, ['Louisiana'] = true, ['Mississippi'] = true, ['North Carolina'] = true, ['Oklahoma'] = true, ['South Carolina'] = true, ['Tennessee'] = true, ['Texas'] = true, ['Virginia'] = true, ['West Virginia'] = true }, ['Northeast'] = {['Connecticut'] = true, ['Delaware'] = true, ['Maine'] = true, ['Maryland'] = true, ['Massachusetts'] = true, ['New Hampshire'] = true, ['New Jersey'] = true, ['New York'] = true, ['Pennsylvania'] = true, ['Rhode Island'] = true, ['Vermont'] = true }, ['Midwest'] = {['Illinois'] = true, ['Indiana'] = true, ['Iowa'] = true, ['Kansas'] = true, ['Michigan'] = true, ['Minnesota'] = true, ['Missouri'] = true, ['Nebraska'] = true, ['North Dakota'] = true, ['Ohio'] = true, ['South Dakota'] = true, ['Wisconsin'] = true} }, ['Canada'] = {['Alberta'] = true, ['British Columbia'] = true, ['Manitoba'] = true, ['New Brunswick'] = true, ['Newfoundland'] = true, ['Northwest Territories'] = true, ['Nova Scotia'] = true, ['Nunavut'] = true, ['Ontario'] = true, ['Prince Edward Island'] = true, ['Quebec'] = true, ['Saskatchewan'] = true, ['Yukon'] = true}, ['Mexico'] = true, ['Central America'] = true, ['Europe'] = {['France'] = true, ['Germany'] = true, ['Spain'] = true, ['Italy'] = true, ['Poland'] = true, ['Switzerland'] = true, ['Greece'] = true, ['Romania'] = true, ['Netherlands'] = true, ['Great Britain'] = {['England'] = true, ['Scotland'] = true, ['Wales'] = true, ['Northern Ireland'] = true} }, ['Asia'] = { ['China'] = true, ['India'] = true, ['Japan'] = true, ['Korea'] = true, ['Russia'] = true, ['Vietnam'] = true}, ['South America'] = { ['Argentina'] = true, ['Brazil'] = true}, ['Africa'] = { ['Eygpt'] = true, ['Swaziland'] = true}, ['Australia'] = true, ['Middle East'] = true, ['Antarctica'] = true, ['New Zealand'] = true }, ['Age'] = {'/sc 6_10', true, ['Rugrat'] = true, ['Kid'] = true, ['Tween'] = true, ['Teen'] = true, ['Twenties'] = true, ['Old'] = true, ['Ancient'] = true, ['Mesozoic'] = true, ['I don\'t want to say my age. Don\'t ask.'] = true}, ['Mood'] = {'/sc 6_11', true, ['Good'] = true, ['Great!'] = true, ['Not bad'] = true, ['Sad'] = true, ['Hyper'] = true, ['Chill'] = true, ['Happy'] = true, ['Kind of mad'] = true}, ['Boy'] = {'/sc 6_12', true}, ['Girl'] = {'/sc 6_13', true}, ['I don\'t want to say boy or girl. Don\'t ask.'] = {'/sc 6_14', true}, [1] = '/sc 6' }, ['Game'] = { ['Let\'s build'] = {'/sc 7_0', true}, ['Let\'s battle'] = {'/sc 7_1', true}, ['Nice one!'] = {'/sc 7_2', true}, ['So far so good'] = {'/sc 7_3', true}, ['Lucky shot!'] = {'/sc 7_4', true}, ['Oh man!'] = {'/sc 7_5', true}, ['I challenge you to a fight!'] = {'/sc 7_6', true}, ['Help me with this'] = {'/sc 7_7', true}, ['Let\'s go to your game'] = {'/sc 7_8', true}, ['Can you show me how do to that?'] = {'/sc 7_9', true}, ['Backflip!'] = {'/sc 7_10', true}, ['Frontflip!'] = {'/sc 7_11', true}, ['Dance!'] = {'/sc 7_12', true}, ['I\'m on your side!'] = {'/sc 7_13', true}, ['Game Commands'] = {'/sc 7_14', true, ['regen'] = true, ['reset'] = true, ['go'] = true, ['fix'] = true, ['respawn'] = true}, [1] = '/sc 7' }; ['Silly'] = { ['Muahahahaha!'] = true, ['all your base are belong to me!'] = true, ['GET OFF MAH LAWN'] = true, ['TEH EPIK DUCK IS COMING!!!'] = true, ['ROFL'] = true, ['1337'] = {true, ['i r teh pwnz0r!'] = true, ['w00t!'] = true, ['z0mg h4x!'] = true, ['ub3rR0xXorzage!'] = true} }, ['Yes'] = { ['Absolutely!'] = true, ['Rock on!'] = true, ['Totally!'] = true, ['Juice!'] = true, ['Yay!'] = true, ['Yesh'] = true }, ['No'] = { ['Ummm. No.'] = true, ['...'] = true, ['Stop!'] = true, ['Go away!'] = true, ['Don\'t do that'] = true, ['Stop breaking the rules'] = true, ['I don\'t want to'] = true }, ['Ok'] = { ['Well... ok'] = true, ['Sure'] = true }, ['Uncertain'] = { ['Maybe'] = true, ['I don\'t know'] = true, ['idk'] = true, ['I can\'t decide'] = true, ['Hmm...'] = true }, [':-)'] = { [':-('] = true, [':D'] = true, [':-O'] = true, ['lol'] = true, ['=D'] = true, ['D='] = true, ['XD'] = true, [';D'] = true, [';)'] = true, ['O_O'] = true, ['=)'] = true, ['@_@'] = true, ['&gt;_&lt;'] = true, ['T_T'] = true, ['^_^'] = true, ['<(0_0<) <(0_0)> (>0_0)> KIRBY DANCE'] = true, [')\';'] = true, [':3'] = true }, ['Ratings'] = { ['Rate it!'] = true, ['I give it a 1 out of 10'] = true, ['I give it a 2 out of 10'] = true, ['I give it a 3 out of 10'] = true, ['I give it a 4 out of 10'] = true, ['I give it a 5 out of 10'] = true, ['I give it a 6 out of 10'] = true, ['I give it a 7 out of 10'] = true, ['I give it a 8 out of 10'] = true, ['I give it a 9 out of 10'] = true, ['I give it a 10 out of 10!'] = true, } }, CreateEnum('SafeChat'){'Level1', 'Level2', 'Level3'}, SafeChatTree = {}, TempSpaceLabel = nil } --------------------------------------------------- local function GetNameValue(pName) local value = 0 for index = 1, #pName do local cValue = string.byte(string.sub(pName, index, index)) local reverseIndex = #pName - index + 1 if #pName%2 == 1 then reverseIndex = reverseIndex - 1 end if reverseIndex%4 >= 2 then cValue = -cValue end value = value + cValue end return value%8 end function Chat:ComputeChatColor(pName) return self.ChatColors[GetNameValue(pName) + 1].Color end -- This is context based scrolling function Chat:EnableScrolling(toggle) -- Genius idea gone to fail, if we switch the camera type we can effectively lock the -- camera and do no click scrolling self.MouseOnFrame = false if self.RenderFrame then self.RenderFrame.MouseEnter:connect(function() local character = Player.Character local torso = WaitForChild(character, 'Torso') local humanoid = WaitForChild(character, 'Humanoid') local head = WaitForChild(character, 'Head') if toggle then self.MouseOnFrame = true Camera.CameraType = 'Scriptable' -- Get relative position of camera and keep to it Spawn(function() local currentRelativePos = Camera.CoordinateFrame.p - torso.Position while Chat.MouseOnFrame do Camera.CoordinateFrame = CFrame.new(torso.Position + currentRelativePos, head.Position) wait(0.015) end end) end end) self.RenderFrame.MouseLeave:connect(function() Camera.CameraType = 'Custom' self.MouseOnFrame = false end) end end -- TODO: Scrolling using Mouse wheel function Chat:OnScroll(speed) if self.MouseOnFrame then -- end end -- Check if we are running on a touch device function Chat:IsTouchDevice() local touchEnabled = false pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end) return touchEnabled end -- Scrolling function Chat:ScrollQueue(value) --[[for i = 1, #self.MessageQueue do if self.MessageQueue[i] then for _, label in pairs(self.MessageQueue[i]) do local next = self.MessageQueue[i].Next local previous = self.MessageQueue[i].Previous if label and label:IsA('TextLabel') or label:IsA('TextButton') then if value > 0 and previous and previous['Message'] then label.Position = previous['Message'].Position elseif value < 1 and next['Message'] then label.Position = previous['Message'].Position end end end end end ]] end -- Handles the rendering of the text objects in their appropriate places function Chat:UpdateQueue(field, diff) -- Have to do some sort of correction here for i = #self.MessageQueue, 1, -1 do if self.MessageQueue[i] then for _, label in pairs(self.MessageQueue[i]) do if label and type(label) ~= 'table' and type(label) ~= 'number' then if label:IsA('TextLabel') or label:IsA('TextButton') then if diff then label.Position = label.Position - UDim2.new(0, 0, diff, 0) else if field == self.MessageQueue[i] then label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale , 0) -- Just to show up popping effect for the latest message in chat Spawn(function() wait(0.05) while label.TextTransparency >= 0 do label.TextTransparency = label.TextTransparency - 0.2 wait(0.03) end if label == field['Message'] then label.TextStrokeTransparency = 0.8 else label.TextStrokeTransparency = 1.0 end end) else label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale, 0) end if label.Position.Y.Scale < -0.01 then -- NOTE: Remove this fix when Textbounds is fixed label.Visible = false label:Destroy() end end end end end end end end function Chat:CreateScrollBar() -- Code for scrolling is in here, partially, but scroll bar drawing isn't drawn -- TODO: Implement end -- For scrolling, to see if we hit the bounds so that we can stop it from scrolling anymore function Chat:CheckIfInBounds(value) if #Chat.MessageQueue < 3 then return true end if value > 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale == 0 then return true elseif value < 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale < 0 then return true else return false end return false end -- This is to precompute all playerName space strings -- This is used to offset the message by exactly this + 2 spacestrings function Chat:ComputeSpaceString(pLabel) local nString = " " if not self.TempSpaceLabel then self.TempSpaceLabel = Create'TextButton' { Size = UDim2.new(0, pLabel.AbsoluteSize.X, 0, pLabel.AbsoluteSize.Y); FontSize = self.Configuration.FontSize; Parent = self.RenderFrame; BackgroundTransparency = 1.0; Text = nString; Name = 'SpaceButton' }; else self.TempSpaceLabel.Text = nString end while self.TempSpaceLabel.TextBounds.X < pLabel.TextBounds.X do nString = nString .. " " self.TempSpaceLabel.Text = nString end nString = nString .. " " self.CachedSpaceStrings_List[pLabel.Text] = nString self.TempSpaceLabel.Text = "" return nString end -- When the playerChatted event fires -- The message is what the player chatted function Chat:UpdateChat(cPlayer, message) local messageField = { ['Player'] = cPlayer, ['Message'] = message } if coroutine.status(Chat.MessageThread) == 'dead' then --Chat.Messages_List = {} table.insert(Chat.Messages_List, messageField) Chat.MessageThread = coroutine.create(function() for i = 1, #Chat.Messages_List do local field = Chat.Messages_List[i] Chat:CreateMessage(field['Player'], field['Message']) end Chat.Messages_List = {} end) coroutine.resume(Chat.MessageThread) else table.insert(Chat.Messages_List, messageField) end end function Chat:RecalculateSpacing() --[[for i = 1, #self.MessageQueue do local pLabel = self.MessageQueue[i]['Player'] local mLabel = self.MessageQueue[i]['Message'] local prevYScale = mLabel.Size.Y.Scale local prevText = mLabel.Text mLabel.Text = prevText local heightField = mLabel.TextBounds.Y mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0) pLabel.Size = mLabel.Size local diff = mLabel.Size.Y.Scale - prevYScale Chat:UpdateQueue(self.MessageQueue[i], diff) end ]] end function Chat:ApplyFilter(str) --[[for _, word in pair(self.Filter_List) do if string.find(str, word) then str:gsub(word, '@#$^') end end ]] end -- NOTE: Temporarily disabled ring buffer to allow for chat to always wrap around function Chat:CreateMessage(cPlayer, message) local pName if not cPlayer then pName = '' else pName = cPlayer.Name end message = StringTrim(message) local pLabel local mLabel -- Our history stores upto 50 messages that is 100 textlabels -- If we ever hit the mark, which would be in every popular game btw -- we wrap around and reuse the labels if #self.MessageQueue > self.Configuration.HistoryLength then --[[pLabel = self.MessageQueue[#self.MessageQueue]['Player'] mLabel = self.MessageQueue[#self.MessageQueue]['Message'] pLabel.Text = pName .. ':' pLabel.Name = pName local pColor if cPlayer.Neutral then pLabel.TextColor3 = Chat:ComputeChatColor(pName) else pLabel.TextColor3 = cPlayer.TeamColor.Color end local nString if not self.CachedSpaceStrings_List[pName] then nString = Chat:ComputeSpaceString(pLabel) else nString = self.CachedSpaceStrings_List[pName] end mLabel.Text = "" mLabel.Name = pName .. " - message" mLabel.Text = nString .. message; mLabel.Parent = nil mLabel.Parent = self.RenderFrame mLabel.Position = UDim2.new(0, 0, 1, 0); pLabel.Position = UDim2.new(0, 0, 1, 0);]] -- Reinserted at the beginning, ring buffer self.MessageQueue[#self.MessageQueue] = nil end --else -- Haven't hit the mark yet, so keep creating pLabel = Create'TextLabel' { Name = pName; Text = pName .. ":"; TextColor3 = pColor; FontSize = Chat.Configuration.FontSize; TextXAlignment = Enum.TextXAlignment.Left; TextYAlignment = Enum.TextYAlignment.Top; Parent = self.RenderFrame; TextWrapped = false; Size = UDim2.new(1, 0, 0.1, 0); BackgroundTransparency = 1.0; TextTransparency = 1.0; Position = UDim2.new(0, 0, 1, 0); BorderSizePixel = 0.0; TextStrokeColor3 = Color3.new(0.5, 0.5, 0.5); TextStrokeTransparency = 0.75; --Active = false; }; local pColor if cPlayer.Neutral then pLabel.TextColor3 = Chat:ComputeChatColor(pName) else pLabel.TextColor3 = cPlayer.TeamColor.Color end local nString if not self.CachedSpaceStrings_List[pName] then nString = Chat:ComputeSpaceString(pLabel) else nString = self.CachedSpaceStrings_List[pName] end mLabel = Create'TextLabel' { Name = pName .. ' - message'; -- Max is 3 lines Size = UDim2.new(1, 0, 0.5, 0); TextColor3 = Chat.Configuration.MessageColor; FontSize = Chat.Configuration.FontSize; TextXAlignment = Enum.TextXAlignment.Left; TextYAlignment = Enum.TextYAlignment.Top; Text = ""; -- this is to stop when the engine reverts the swear words to default, which is button, ugh Parent = self.RenderFrame; TextWrapped = true; BackgroundTransparency = 1.0; TextTransparency = 1.0; Position = UDim2.new(0, 0, 1, 0); BorderSizePixel = 0.0; TextStrokeColor3 = Color3.new(0, 0, 0); --TextStrokeTransparency = 0.8; --Active = false; }; mLabel.Text = nString .. message; if not pName then pLabel.Text = '' mLabel.TextColor3 = Color3.new(0, 0.4, 1.0) end --end for _, adminName in pairs(self.Admins_List) do if string.lower(adminName) == string.lower(pName) then mLabel.TextColor3 = self.Configuration.AdminMessageColor end end pLabel.Visible = true mLabel.Visible = true -- This will give beautiful multilines as well local heightField = mLabel.TextBounds.Y mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0) pLabel.Size = mLabel.Size local yPixels = self.RenderFrame.AbsoluteSize.Y local yFieldSize = mLabel.TextBounds.Y local queueField = {} queueField['Player'] = pLabel queueField['Message'] = mLabel queueField['SpawnTime'] = tick() -- Used for identifying when to make the message invisible table.insert(self.MessageQueue, 1, queueField) Chat:UpdateQueue(queueField) end function Chat:ScreenSizeChanged() wait() while self.Frame.AbsoluteSize.Y > 120 do self.Frame.Size = self.Frame.Size - UDim2.new(0, 0, 0.005, 0) end Chat:RecalculateSpacing() end function Chat:FindButtonTree(scButton, rootList) local list = {} rootList = rootList or self.SafeChatTree for button, _ in pairs(rootList) do if button == scButton then list = rootList[button] elseif type(rootList[button]) == 'table' then list = Chat:FindButtonTree(scButton, rootList[button]) end end return list end function Chat:ToggleSafeChatMenu(scButton) local list = Chat:FindButtonTree(scButton, self.SafeChatTree) if list then for button, _ in pairs(list) do if button:IsA('TextButton') or button:IsA('ImageButton') then button.Visible = not button.Visible end end return true end return false end function Chat:CreateSafeChatOptions(list, rootButton) local text_List = {} level = level or 0 local count = 0 text_List[rootButton] = {} text_List[rootButton][1] = list[1] rootButton = rootButton or self.SafeChatButton for msg, _ in pairs(list) do if type(msg) == 'string' then local chatText = Create'TextButton' { Name = msg; Text = msg; Size = UDim2.new(0, 100, 0, 20); TextXAlignment = Enum.TextXAlignment.Center; TextColor3 = Color3.new(0.2, 0.1, 0.1); BackgroundTransparency = 0.5; BackgroundColor3 = Color3.new(1, 1, 1); Parent = self.SafeChatFrame; Visible = false; Position = UDim2.new(0, rootButton.Position.X.Scale + 105, 0, rootButton.Position.Y.Scale - ((count - 3) * 100)); }; count = count + 1 if type(list[msg]) == 'table' then text_List[rootButton][chatText] = Chat:CreateSafeChatOptions(list[msg], chatText) else --table.insert(text_List[chatText], true) end chatText.MouseEnter:connect(function() Chat:ToggleSafeChatMenu(chatText) end) chatText.MouseLeave:connect(function() Chat:ToggleSafeChatMenu(chatText) end) chatText.MouseButton1Click:connect(function() local lList = Chat:FindButtonTree(chatText) if lList then for i, v in pairs(lList) do end else end pcall(function() PlayersService:Chat(lList[1]) end) end) end end return text_List end function Chat:CreateSafeChatGui() self.SafeChatFrame = Create'Frame' { Name = 'SafeChatFrame'; Size = UDim2.new(1, 0, 1, 0); Parent = self.Gui; BackgroundTransparency = 1.0; Create'ImageButton' { Name = 'SafeChatButton'; Size = UDim2.new(0, 44, 0, 31); Position = UDim2.new(0, 1, 0.35, 0); BackgroundTransparency = 1.0; Image = 'http://www.roblox.com/asset/?id=97080365'; }; } self.SafeChatButton = self.SafeChatFrame.SafeChatButton -- safe chat button is the root of this tree self.SafeChatTree[self.SafeChatButton] = Chat:CreateSafeChatOptions(self.SafeChat_List, self.SafeChatButton) self.SafeChatButton.MouseButton1Click:connect(function() Chat:ToggleSafeChatMenu(self.SafeChatButton) end) end function Chat:FocusOnChatBar() if self.ClickToChatButton then self.ClickToChatButton.Visible = false end self.GotFocus = true if self.Frame['Background'] then self.Frame.Background.Visible = false end self.ChatBar:CaptureFocus() end -- For touch devices we create a button instead function Chat:CreateTouchButton() self.ChatTouchFrame = Create'Frame' { Name = 'ChatTouchFrame'; Size = UDim2.new(0, 128, 0, 32); Position = UDim2.new(0, 88, 0, 0); BackgroundTransparency = 1.0; Parent = self.Gui; Create'ImageButton' { Name = 'ChatLabel'; Size = UDim2.new(0, 74, 0, 28); Position = UDim2.new(0, 0, 0, 0); BackgroundTransparency = 1.0; ZIndex = 2.0; }; Create'ImageLabel' { Name = 'Background'; Size = UDim2.new(1, 0, 1, 0); Position = UDim2.new(0, 0, 0, 0); BackgroundTransparency = 1.0; Image = 'http://www.roblox.com/asset/?id=97078724' }; } self.TapToChatLabel = self.ChatTouchFrame.ChatLabel self.TouchLabelBackground = self.ChatTouchFrame.Background self.ChatBar = Create'TextBox' { Name = 'ChatBar'; Size = UDim2.new(1, 0, 0.2, 0); Position = UDim2.new(0, 0, 0.8, 800); Text = ""; ZIndex = 1.0; BackgroundTransparency = 1.0; Parent = self.Frame; TextXAlignment = Enum.TextXAlignment.Left; TextColor3 = Color3.new(1, 1, 1); ClearTextOnFocus = false; }; self.TapToChatLabel.MouseButton1Click:connect(function() self.TapToChatLabel.Visible = false --self.ChatBar.Visible = true --self.Frame.Background.Visible = true self.ChatBar:CaptureFocus() self.GotFocus = true if self.TouchLabelBackground then self.TouchLabelBackground.Visible = false end end) end -- Non touch devices, create the bottom chat bar function Chat:CreateChatBar() -- okay now we do local status, result = pcall(function() return GuiService.UseLuaChat end) if status and result then self.ClickToChatButton = Create'TextButton' { Name = 'ClickToChat'; Size = UDim2.new(1, 0, 0, 20); BackgroundTransparency = 1.0; ZIndex = 2.0; Parent = self.Gui; Text = "To chat click here or press \"/\" key"; TextColor3 = Color3.new(1, 1, 0.9); Position = UDim2.new(0, 0, 1, 0); TextXAlignment = Enum.TextXAlignment.Left; FontSize = Enum.FontSize.Size12; } self.ChatBar = Create'TextBox' { Name = 'ChatBar'; Size = UDim2.new(1, 0, 0, 20); Position = UDim2.new(0, 0, 1, 0); Text = ""; ZIndex = 1.0; BackgroundColor3 = Color3.new(0, 0, 0); BackgroundTransparency = 0.25; Parent = self.Gui; TextXAlignment = Enum.TextXAlignment.Left; TextColor3 = Color3.new(1, 1, 1); FontSize = Enum.FontSize.Size12; ClearTextOnFocus = false; Text = ''; }; -- Engine has code to offset the entire world, so if we do it by -20 pixels nothing gets in our chat's way GuiService:SetGlobalSizeOffsetPixel(0, -20) -- CHatHotKey is '/' GuiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey) GuiService.SpecialKeyPressed:connect(function(key) if key == Enum.SpecialKey.ChatHotkey then Chat:FocusOnChatBar() end end) self.ClickToChatButton.MouseButton1Click:connect(function() Chat:FocusOnChatBar() end) end end -- Create the initial Chat stuff -- Done only once function Chat:CreateGui() self.Gui = script.Parent self.Frame = Create'Frame' { Name = 'ChatFrame'; --Size = self.Configuration.Size; Size = UDim2.new(0, 500, 0, 120); Position = UDim2.new(0, 0, 0, 5); BackgroundTransparency = 1.0; --ClipsDescendants = true; ZIndex = 0.0; Parent = self.Gui; Active = false; Create'ImageLabel' { Name = 'Background'; Image = 'http://www.roblox.com/asset/?id=97120937'; --96551212'; Size = UDim2.new(1.3, 0, 1.64, 0); Position = UDim2.new(0, 0, 0, 0); BackgroundTransparency = 1.0; ZIndex = 0.0; Visible = false }; Create'Frame' { Name = 'Border'; Size = UDim2.new(1, 0, 0, 1); Position = UDim2.new(0, 0, 0.8, 0); BackgroundTransparency = 0.0; BackgroundColor3 = Color3.new(236/255, 236/255, 236/255); BorderSizePixel = 0.0; Visible = false; }; Create'Frame' { Name = 'ChatRenderFrame'; Size = UDim2.new(1.02, 0, 1.01, 0); Position = UDim2.new(0, 0, 0, 0); BackgroundTransparency = 1.0; --ClipsDescendants = true; ZIndex = 0.0; Active = false; }; }; Spawn(function() wait(0.5) if IsPhone() then self.Frame.Size = UDim2.new(0, 280, 0, 120) end end) self.RenderFrame = self.Frame.ChatRenderFrame if Chat:IsTouchDevice() then self.Frame.Position = self.Configuration.Position; self.RenderFrame.Size = UDim2.new(1, 0, 1, 0) elseif self.Frame.AbsoluteSize.Y > 120 then Chat:ScreenSizeChanged() self.Gui.Changed:connect(function(property) if property == 'AbsoluteSize' then Chat:ScreenSizeChanged() end end) end if Player.ChatMode == Enum.ChatMode.TextAndMenu then if Chat:IsTouchDevice() then Chat:CreateTouchButton() else Chat:CreateChatBar() --Chat:CreateSafeChatGui() end if self.ChatBar then self.ChatBar.FocusLost:connect(function(enterPressed) Chat.GotFocus = false if Chat:IsTouchDevice() then self.ChatBar.Visible = false self.TapToChatLabel.Visible = true if self.TouchLabelBackground then self.TouchLabelBackground.Visible = true end end if enterPressed and self.ChatBar.Text ~= "" then local cText = self.ChatBar.Text if string.sub(self.ChatBar.Text, 1, 1) == '%' then cText = '(TEAM) ' .. string.sub(cText, 2, #cText) pcall(function() PlayersService:TeamChat(cText) end) else pcall(function() PlayersService:Chat(cText) end) end if self.ClickToChatButton then self.ClickToChatButton.Visible = true end self.ChatBar.Text = "" end Spawn(function() wait(5.0) if not Chat.GotFocus then Chat.Frame.Background.Visible = false end end) end) end end end -- Scrolling function -- Applies a speed(velocity) to have nice scrolling effect function Input:OnMouseScroll() Spawn(function() -- How long should the speed last? while Input.Speed ~=0 do if Input.Speed > 1 then while Input.Speed > 0 do Input.Speed = Input.Speed - 1 wait(0.25) end elseif Input.Speed < 0 then while Input.Speed < 0 do Input.Speed = Input.Speed + 1 wait(0.25) end end wait(0.03) end end) if Chat:CheckIfInBounds(Input.Speed) then return end Chat:ScrollQueue() end function Input:ApplySpeed(value) Input.Speed = Input.Speed + value if not self.Simulating then Input:OnMouseScroll() end end function Input:Initialize() self.Mouse.WheelBackward:connect(function() Input:ApplySpeed(self.Configuration.DefaultSpeed) end) self.Mouse.WheelForward:connect(function() Input:ApplySpeed(self.Configuration.DefaultSpeed) end) end function Chat:FindMessageInSafeChat(message, list) local foundMessage = false for msg, _ in pairs(list) do if msg == message then return true end if type(list[msg]) == 'table' then foundMessage = Chat:FindMessageInSafeChat(message, list[msg]) if foundMessage then return true end end end return foundMessage end -- Just a wrapper around our PlayerChatted event function Chat:PlayerChatted(...) local args = {...} local argCount = select('#', ...) local player local message -- This doesn't look very good, but what else to do? if args[2] then player = args[2] end if args[3] then message = args[3] if string.sub(message, 1, 1) == '%' then message = '(TEAM) ' .. string.sub(message, 2, #message) end end if PlayersService.ClassicChat then if Player.ChatMode == Enum.ChatMode.TextAndMenu then Chat:UpdateChat(player, message) elseif Player.ChatMode == Enum.ChatMode.Menu and string.sub(message, 3) == '/sc' then Chat:UpdateChat(player, message) else if Chat:FindMessageInSafeChat(message, self.SafeChat_List) then Chat:UpdateChat(player, message) end end end end -- After Chat.Configuration.Lifetime seconds of existence, the labels become invisible -- Runs only every 5 seconds and has to loop through 50 values -- Shouldn't be too expensive function Chat:CullThread() while true do if #self.MessageQueue > 0 then for _, field in pairs(self.MessageQueue) do if field['SpawnTime'] and field['Player'] and field['Message'] and tick() - field['SpawnTime'] > self.Configuration.LifeTime then field['Player'].Visible = false field['Message'].Visible = false end end end wait(5.0) end end -- RobloxLock everything so users can't delete them(?) function Chat:LockAllFields(gui) end -- Constructor -- This function initializes everything function Chat:Initialize() Chat:CreateGui() self.EventListener = PlayersService.PlayerChatted:connect(function(...) -- This event has 4 callback arguments -- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer Chat:PlayerChatted(...) end) self.MessageThread = coroutine.create(function() end) coroutine.resume(self.MessageThread) -- Initialize input for us Input:Initialize() -- Eww, everytime a player is added, you have to redo the connection -- Seems this is not automatic -- NOTE: PlayerAdded only fires on the server, hence ChildAdded is used here PlayersService.ChildAdded:connect(function() Chat.EventListener:disconnect() self.EventListener = PlayersService.PlayerChatted:connect(function(...) -- This event has 4 callback arguments -- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer Chat:PlayerChatted(...) end) end) Spawn(function() Chat:CullThread() end) self.Frame.DescendantAdded:connect(function(descendant) end) end Chat:Initialize()