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.Notifications:clone().Parent = game.StarterGui script:remove() true ReenableDialogScript 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 TimeoutScript wait(5) local dialog = script.Parent if dialog:IsA("Dialog") then dialog.InUse = false end script:Remove() 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 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 false Workaround local function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end end waitForChild(game, "NetworkClient") wait(0.1) game.Players.LocalPlayer.PlayerGui.Menu.MenuScript.Disabled = true game.Players.LocalPlayer.PlayerGui.Menu.MenuScript.Disabled = false if game.NetworkClient == nil then print("Playing solo, not using workaround.") 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.OKButton.Visible = false 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 --fixed by Carrot#0559 --for non corescript use 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 --rbxsig%bMgJMPt2chG7JIOhV0y5so/4dL1lRGiT3ELG0LsKh4QrqkG8sRdndraomuViGbDkVOWLXwIilzkhlSJSCjgZ9zXp6fS+SekW/n/RVWjNLA/gPThKLVxP6HmHRK9WTzIQ4ZTXjBmaExcdxBb1remqDPHWHlO2QoxZBqHs5sDGlQI=% --rbxassetid%48488235% local RbxGui 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", } local localTesting = true local screen = script.Parent local screenResizeCon = nil local friendWord = "Friend" local friendWordLowercase = "friend" local elementNames = {} local elementNameToElement = {} local privilegeOwner = 255 local privilegeAdmin = 240 local privilegeMember = 128 local privilegeVisitor = 10 local privilegeBanned = 0 local inContextMenu = false local contextMenu3d = false local bigEasingStyle = Enum.EasingStyle.Back local smallEasingStyle = Enum.EasingStyle.Quart local personalServerContextAdded = false local personalServerPlace = false local success = pcall(function() personalServerPlace = game.IsPersonalServer end) if not success then personalServerPlace = false end local friendRequestBlacklist = {} local otherPlayerBlacklist = {} local currentSortName = "" local function waitForChild(instance, name) while not instance:FindFirstChild(name) do instance.ChildAdded:wait() end end local function waitForProperty(instance, prop) while not instance[prop] do instance.Changed:wait() end end local function Color3I(r,g,b) return Color3.new(r/255,g/255,b/255) end function robloxLock(instance) end function ArrayRemove(t, obj) for i, obj2 in ipairs(t) do if obj == obj2 then table.remove(t, i) return true end end return false end local function getPlayers() local result = {} local players = game:GetService("Players"):GetChildren() if players then for i, player in ipairs(players) do if player:IsA("Player") then table.insert(result, player) end end end return result end local brickColorTable = {} for i = 0, 63 do brickColorTable[BrickColor.palette(i).Name] = BrickColor.palette(i).Color end local function remapColor(i, j) brickColorTable[BrickColor.palette(i).Name] = BrickColor.palette(j).Color end remapColor(13, 12) remapColor(14, 12) remapColor(15, 12) remapColor(61, 29) remapColor(63, 62) remapColor(56, 50) remapColor(45, 53) remapColor(51, 20) remapColor(4, 20) remapColor(59, 35) remapColor(60, 29) local function getColor(brickColor) if brickColorTable[brickColor.Name] then return brickColorTable[brickColor.Name] else return brickColor.Color; end end local function getTeams() local result = {} local teams = game:GetService("Teams"):GetChildren() for i, team in ipairs(teams) do if team:IsA("Team") then table.insert(result, team) end end return result end local supportFriends = true local currentBoardType = "PlayerList" local currentStatCount = 0 local createBoardsFunction = nil local playerTable = {} local teamTable = {} local teamColorTable = {} local removePlayerFunction = nil local recreatePlayerFunction = nil local addPlayerFunction = function(player) if recreatePlayerFunction then recreatePlayerFunction(player) end end local sortPlayerListsFunction = nil local minimizedState = nil local bigWindowImposter = nil local smallWindowPosition = UDim2.new(0, -20, 0,5) local smallWindowSize = UDim2.new(1,0,1,0) local bigWindowSize = UDim2.new(0.6,0,0.6,0) local bigWindowPosition = UDim2.new(.2, 0, .2,0) local smallWindowHeaderYSize = 32 local debounceTeamsChanged = false local currentWindowState = "Small" local previousWindowState = nil local transitionWindowsFunction = nil local container = nil local topRightTrayContainer = nil local playerContextMenu = nil local contextMenuElements = {} local updateContextMenuItems = nil local function addContextMenuLabel(getText1, getText2, isVisible) local t = {} t.Type = "Label" t.GetText1 = getText1 t.GetText2 = getText2 t.IsVisible = isVisible table.insert(contextMenuElements, t) end local function addContextMenuButton(text, isVisible, isActive, doIt) local t = {} t.Text = text t.Type = "Button" t.IsVisible = isVisible t.IsActive = isActive t.DoIt = doIt table.insert(contextMenuElements, t) end 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 local function getPrivilegeType(player) local rank = player.PersonalServerRank if rank >= privilegeOwner then return privilegeOwner elseif rank < privilegeOwner and rank >= privilegeAdmin then return privilegeAdmin elseif rank < privilegeAdmin and rank >= privilegeMember then return privilegeMember elseif rank < privilegeMember and rank >= privilegeVisitor then return privilegeVisitor else return privilegeBanned end end --Populate the ContextMenus addContextMenuLabel( --GetText1 function(player) return "Loading..." end, --GetText2 nil, --IsVisible function(player) return getFriendStatus(player) == Enum.FriendStatus.Unknown end) addContextMenuButton("Send " .. friendWord .. " Request", --IsVisible function(player) return (not otherPlayerBlacklist[player]) and (getFriendStatus(player) == Enum.FriendStatus.NotFriend) end, --IsActive function(player) return true end, --DoIt? function(player) otherPlayerBlacklist[player] = true return game.Players.LocalPlayer:RequestFriendship(player) end ) addContextMenuButton("Un" .. friendWordLowercase, --IsVisible function(player) return getFriendStatus(player) == Enum.FriendStatus.Friend end, --IsActive function(player) return true end, --DoIt function(player) return game.Players.LocalPlayer:RevokeFriendship(player) end ) addContextMenuButton("Accept " .. friendWord .. " Request", --IsVisible function(player) return (not friendRequestBlacklist[player]) and (getFriendStatus(player) == Enum.FriendStatus.FriendRequestReceived) end, --IsActive function(player) return true end, --DoIt function(player) return game.Players.LocalPlayer:RequestFriendship(player) end ) addContextMenuButton("Deny " .. friendWord .. " Request", --IsVisible function(player) return getFriendStatus(player) == Enum.FriendStatus.FriendRequestReceived end, --IsActive function(player) return true end, --DoIt function(player) friendRequestBlacklist[player] = true return game.Players.LocalPlayer:RevokeFriendship(player) end ) addContextMenuButton("Cancel " .. friendWord .. " Request", --IsVisible function(player) return false -- disable cancel request for now (can lead to griefing) --return getFriendStatus(player) == Enum.FriendStatus.FriendRequestSent end, --IsActive function(player) return true end, --DoIt function(player) otherPlayerBlacklist[player] = false return game.Players.LocalPlayer:RevokeFriendship(player) end ) function addPersonalServerContext() if personalServerContextAdded then return end personalServerContextAdded = true addContextMenuButton("Ban", --IsVisible function(player) return ( getPrivilegeType(game.Players.LocalPlayer) >= privilegeAdmin and (getPrivilegeType(player) < privilegeAdmin) ) end, --IsActive function(player) return true end, --DoIt function(player) player.PersonalServerRank = privilegeBanned return true end ) addContextMenuButton("Promote to Visitor", --IsVisible function(player) return ( getPrivilegeType(game.Players.LocalPlayer) >= privilegeAdmin ) and ( getPrivilegeType(player) == privilegeBanned ) end, --IsActive function(player) return true end, --DoIt function(player) game:GetService("PersonalServerService"):Promote(player) return true end ) addContextMenuButton("Promote to Member", --IsVisible function(player) return ( getPrivilegeType(game.Players.LocalPlayer) >= privilegeAdmin ) and ( getPrivilegeType(player) == privilegeVisitor ) end, --IsActive function(player) return true end, --DoIt function(player) game:GetService("PersonalServerService"):Promote(player) return true end ) addContextMenuButton("Promote to Admin", --IsVisible function(player) return ( getPrivilegeType(game.Players.LocalPlayer) == privilegeOwner ) and ( getPrivilegeType(player) == privilegeMember ) end, --IsActive function(player) return true end, --DoIt function(player) game:GetService("PersonalServerService"):Promote(player) return true end ) addContextMenuButton("Demote to Member", --IsVisible function(player) return ( getPrivilegeType(game.Players.LocalPlayer) == privilegeOwner ) and ( getPrivilegeType(player) == privilegeAdmin ) end, --IsActive function(player) return true end, --DoIt function(player) game:GetService("PersonalServerService"):Demote(player) return true end ) addContextMenuButton("Demote to Visitor", --IsVisible function(player) return ( getPrivilegeType(game.Players.LocalPlayer) >= privilegeAdmin ) and ( getPrivilegeType(player) == privilegeMember ) end, --IsActive function(player) return true end, --DoIt function(player) game:GetService("PersonalServerService"):Demote(player) return true end ) end local function setupBuildToolManagement() local buildToolManagerAssetId = 64164692 game:GetService("ScriptContext"):AddCoreScript(buildToolManagerAssetId,game.Players.LocalPlayer,"BuildToolManager") end local function getStatColumns(players) for i, player in ipairs(players) do local leaderstats = player:FindFirstChild("leaderstats") if leaderstats then local stats = {} local children = leaderstats:GetChildren() if children then for i, stat in ipairs(children) do if stat:IsA("IntValue") then table.insert(stats, stat) else --TODO: This should check for IntValue only but current ScoreHud does not table.insert(stats, stat) end end end return stats end end return nil end local function determineBoardType() local players = getPlayers() local foundLeaderstats = false local numStats = 0 local foundTeam = false local stats = getStatColumns(players) if stats then foundLeaderstats = true numStats = #stats end for i, player in ipairs(players) do if not foundTeam then if not player.Neutral then foundTeam = true break end end end if foundLeaderstats and foundTeam then return "TeamScore", numStats elseif foundLeaderstats then return "PlayerScore", numStats elseif foundTeam then return "TeamList", numStats else return "PlayerList", numStats end end local function toggleBigWindow() if container == nil then return end if currentWindowState == "Big" then --Hide it if previousWindowState == nil or previousWindowState == "Big" or previousWindowState == "None" then transitionWindowsFunction("None") else transitionWindowsFunction("Small") end else previousWindowState = currentWindowState transitionWindowsFunction("Big") end end local previousBigPlayerList = nil local function rebuildBoard(owner, boardType, numStats) if topRightTrayContainer == nil then topRightTrayContainer = owner:FindFirstChild("PlayerListTopRightFrame") if topRightTrayContainer == nil then topRightTrayContainer = Instance.new("Frame") topRightTrayContainer.Name = "PlayerListTopRightFrame" topRightTrayContainer.BackgroundTransparency = 1 topRightTrayContainer.Size = UDim2.new(0.2, 16, 0.42, 16) topRightTrayContainer.Position = UDim2.new(0.8, 0, 0, 0) topRightTrayContainer.Parent = container end end if minimizedState == nil then minimizedState = Instance.new("Frame") minimizedState.Name = "MinimizedPlayerlist" minimizedState.BackgroundTransparency = 1 minimizedState.Position = UDim2.new(1, -166, 0,0) minimizedState.Size = UDim2.new(0, 151, 0, 30) playerListButton = Instance.new("ImageButton") playerListButton.Name = "GoSmallButton" playerListButton.Image = "rbxasset://textures/ui/playerlist_hidden_small.png" playerListButton.BackgroundTransparency = 1 playerListButton.Size = UDim2.new(0.0, 35, 0, 30) playerListButton.Position = UDim2.new(1, -35, 0, 0) playerListButton.MouseButton1Click:connect( function() transitionWindowsFunction("Small") end) playerListButton.Parent = minimizedState minimizedState.Visible = false robloxLock(minimizedState) minimizedState.Parent = topRightTrayContainer end if bigWindowImposter == nil then bigWindowImposter = owner:FindFirstChild("BigPlayerListWindowImposter") if bigWindowImposter == nil then bigWindowImposter = Instance.new("Frame") bigWindowImposter.Name = "BigPlayerListWindowImposter" bigWindowImposter.Visible = false bigWindowImposter.BackgroundColor3 = Color3.new(0,0,0) bigWindowImposter.BackgroundTransparency = 0.7 bigWindowImposter.BorderSizePixel = 0 bigWindowImposter.Size = UDim2.new(0.4, 7, 0.4, 7) bigWindowImposter.Position = UDim2.new(0.3, 0, 0.3, 0) robloxLock(bigWindowImposter) bigWindowImposter.Parent = container end end if container == nil or container ~= owner then container = owner topRightTrayContainer.Parent = container bigWindowImposter.Parent = container end local smallVisible = true local bigVisible = false if container then if topRightTrayContainer then --Delete the old boards if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then smallVisible = topRightTrayContainer.SmallPlayerlist.Visible topRightTrayContainer.SmallPlayerlist.Parent = nil end end if container:FindFirstChild("BigPlayerlist") then bigVisible = container.BigPlayerlist.Visible or (previousBigPlayerList ~= nil) container.BigPlayerlist.Parent = nil if previousBigPlayerList ~= nil then pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) previousBigPlayerList = nil end end end local smallBoard, bigBoard = createBoardsFunction(boardType, numStats) if smallBoard then smallBoard.Visible = smallVisible smallBoard.Parent = topRightTrayContainer recalculateSmallPlayerListSize(smallBoard) end if bigBoard then if bigVisible then previousBigPlayerList = bigBoard local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(previousBigPlayerList, Enum.CenterDialogType.PlayerInitiatedDialog, function() previousBigPlayerList.Visible = true end, function() previousBigPlayerList.Visible = false end) end) bigBoard.Visible = bigVisible else bigBoard.Visible = false end bigBoard.Parent = container end return container end function recalculateSmallPlayerListSize(smallPlayerList) waitForChild(smallPlayerList,"ScrollingArea") waitForChild(smallPlayerList.ScrollingArea, "ScrollingFrame") local scrollingFrame = smallPlayerList.ScrollingArea.ScrollingFrame local playerLines = scrollingFrame:GetChildren() local totalPlayerListSize = 0 for i = 1, #playerLines do totalPlayerListSize = totalPlayerListSize + playerLines[i].AbsoluteSize.Y end if not smallPlayerList.Parent then return end local yOffset = math.max(0,(smallPlayerList.Size.Y.Scale * smallPlayerList.Parent.AbsoluteSize.Y) - totalPlayerListSize - smallWindowHeaderYSize) smallPlayerList.Size = UDim2.new(smallPlayerList.Size.X.Scale,smallPlayerList.Size.X.Offset,smallPlayerList.Size.Y.Scale,-yOffset) end local function showBigPlayerWindow() if container:FindFirstChild("BigPlayerlist") then if container.BigPlayerlist.Visible then return end end bigWindowImposter.Visible = true bigWindowImposter:TweenSizeAndPosition(bigWindowSize, bigWindowPosition, Enum.EasingDirection.Out, bigEasingStyle, 0.3, true, function(state) if state == Enum.TweenStatus.Completed then bigWindowImposter.Visible = false if container:FindFirstChild("BigPlayerlist") then container.BigPlayerlist.Visible = true end end end) end local function hideBigPlayerWindow(completed) if playerContextMenu then playerContextMenu.Visible = false end if container:FindFirstChild("BigPlayerlist") then if container.BigPlayerlist.Visible == false and bigWindowImposter.Visible == false then if completed then completed() end --Already completely hidden return end container.BigPlayerlist.Visible = false end local completedFunction = completed bigWindowImposter.Visible = true bigWindowImposter:TweenSizeAndPosition(UDim2.new(0.4, 0, 0.4, 0), UDim2.new(0.3, 0, 0.3, 0), Enum.EasingDirection.In, Enum.EasingStyle.Quart, 0.15, true, function(state) if state == Enum.TweenStatus.Completed then bigWindowImposter.Visible = false if completedFunction then completedFunction() end end end) end local function hideSmallPlayerWindow(completed) if playerContextMenu then playerContextMenu.Visible = false end if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then local completedFunction = completed if topRightTrayContainer.SmallPlayerlist.Visible then topRightTrayContainer.SmallPlayerlist:TweenPosition(UDim2.new(1,0,smallWindowPosition.Y.Scale, smallWindowPosition.Y.Offset), Enum.EasingDirection.Out, smallEasingStyle, 0.3, true, function(state) if state == Enum.TweenStatus.Completed then if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then topRightTrayContainer.SmallPlayerlist.Visible = false end if completedFunction then completedFunction() end end end) return end end if completed then completed() end end transitionWindowsFunction = function(desiredState) if desiredState == "Big" then minimizedState.Visible = false hideSmallPlayerWindow() if previousBigPlayerList ~= nil then if previousBigPlayerList ~= container:FindFirstChild("BigPlayerlist") then pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) previousBigPlayerList = nil previousBigPlayerList = container:FindFirstChild("BigPlayerlist") end else previousBigPlayerList = container:FindFirstChild("BigPlayerlist") end if previousBigPlayerList then local firstShow = false local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(previousBigPlayerList, Enum.CenterDialogType.PlayerInitiatedDialog, function() if not firstShow then showBigPlayerWindow() firstShow = true else previousBigPlayerList.Visible = true end end, function() if previousBigPlayerList then previousBigPlayerList.Visible = false end end) end) if centerDialogSupported == false then print("Exception", msg) showBigPlayerWindow() end else showBigPlayerWindow() end currentWindowState = "Big" elseif desiredState == "Small" then minimizedState.Visible = false if previousBigPlayerList ~= nil then pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) previousBigPlayerList = nil end hideBigPlayerWindow() if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then if not topRightTrayContainer.SmallPlayerlist.Visible or topRightTrayContainer.SmallPlayerlist.Position ~= smallWindowPosition then topRightTrayContainer.SmallPlayerlist.Visible = true topRightTrayContainer.SmallPlayerlist:TweenPosition(smallWindowPosition, Enum.EasingDirection.Out, smallEasingStyle, 0.3, true) end end currentWindowState = "Small" elseif desiredState == "None" then if previousBigPlayerList ~= nil then pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) previousBigPlayerList = nil end local smallDone = false local bigDone = false hideSmallPlayerWindow( function() smallDone = true if bigDone and smallDone then minimizedState.Visible = true end end) hideBigPlayerWindow( function() bigDone = true if bigDone and smallDone then minimizedState.Visible = true end end) currentWindowState = "None" end end local function getStatValuesForPlayer(player) local leaderstats = player:FindFirstChild("leaderstats") if leaderstats then local children = leaderstats:GetChildren() if children then local result = {} --Just go based on position for i, stat in ipairs(children) do if stat:IsA("IntValue") then table.insert(result, stat) else table.insert(result, 0) end end return result, leaderstats end end return nil end --ChildAdded on Player (if it's name is "leaderstats") if UserSettings and LoadLibrary then RbxGui,msg = t local function createTeamName(name, color) local fontHeight = 20 local frame = Instance.new("Frame") frame.Name = "Team-" .. name frame.BorderSizePixel = 0 frame.BackgroundTransparency = 0.5 frame.BackgroundColor3 = Color3.new(1,1,1) frame.Size = UDim2.new(1, 0, 0, fontHeight) frame.Position = UDim2.new(0,0,0,0) local label = Instance.new("TextLabel") label.Name = "NameLabel" label.Text = " " .. name label.Font = Enum.Font.ArialBold label.FontSize = Enum.FontSize.Size18 label.Position = UDim2.new(0,0,0,0) label.Size = UDim2.new(1,0,1,0) label.TextColor3 = Color3.new(1,1,1) label.BackgroundTransparency = 0.5 label.BackgroundColor3 = getColor(color) label.BorderSizePixel = 0 label.TextXAlignment = Enum.TextXAlignment.Left local changeFunc = nil label, changeFunc = RbxGui.AutoTruncateTextObject(label) label.Parent = frame return frame, changeFunc end local function getFriendStatusIcon(friendStatus) if friendStatus == Enum.FriendStatus.Unknown or friendStatus == Enum.FriendStatus.NotFriend then return nil elseif friendStatus == Enum.FriendStatus.Friend then return "rbxasset://textures/ui/PlayerlistFriendIcon.png" elseif friendStatus == Enum.FriendStatus.FriendRequestSent then return "rbxasset://textures/ui/PlayerlistFriendRequestSentIcon.png" elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then return "rbxasset://textures/ui/PlayerlistFriendRequestReceivedIcon.png" else error("Unknown FriendStatus: " .. friendStatus) end end 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 updatePlayerFriendStatus(nameObject, friendStatus) local fontHeight = 20 local friendIconImage = getFriendStatusIcon(friendStatus) nameObject.MembershipTypeLabel.FriendStatusLabel.Visible = (friendIconImage ~= nil) if friendIconImage ~= nil then --Show friend icon nameObject.MembershipTypeLabel.FriendStatusLabel.Image = friendIconImage nameObject.NameLabel.Position =UDim2.new(0,2*fontHeight,0,1) nameObject.NameLabel.Size = UDim2.new(1,-2*fontHeight,1,-2) else --Hide the friend icon nameObject.NameLabel.Position = UDim2.new(0,fontHeight+1,0,1) nameObject.NameLabel.Size = UDim2.new(1,-(fontHeight+1),1,-2) end end local function updatePlayerName(nameObject, membershipStatus, teamColor) local fontHeight = 20 local membershipType = membershipStatus local playerName = nameObject.NameLabel.Text nameObject.Size = UDim2.new(1,0,0,fontHeight) nameObject.MembershipTypeLabel.Image = getMembershipTypeIcon(membershipType, playerName) end local function updatePlayerNameColor(player, teamColor) local function updatePlayerNameColorHelper(nameObject) if teamColor ~= nil then nameObject.NameLabel.TextColor3 = getColor(teamColor) nameObject.NameLabel.FullNameLabel.TextColor3 = getColor(teamColor) else nameObject.NameLabel.TextColor3 = Color3.new(1,1,1) nameObject.NameLabel.FullNameLabel.TextColor3 = Color3.new(1,1,1) end end updatePlayerNameColorHelper(playerTable[player].NameObjectSmall) updatePlayerNameColorHelper(playerTable[player].NameObjectBig) end local function createPlayerName(name, membershipStatus, teamColor, friendStatus) local frame = Instance.new("Frame") frame.Name = "Player_" .. name frame.BackgroundColor3 = Color3.new(1,1,1) frame.BackgroundTransparency = 0.5 frame.BorderSizePixel = 0 local membershipStatusLabel = Instance.new("ImageLabel") membershipStatusLabel.Name = "MembershipTypeLabel" membershipStatusLabel.BackgroundTransparency = 1 membershipStatusLabel.Size = UDim2.new(0,18,0,18) membershipStatusLabel.Position = UDim2.new(0,0,0,0) membershipStatusLabel.SizeConstraint = Enum.SizeConstraint.RelativeYY membershipStatusLabel.Parent = frame local friendStatusLabel = Instance.new("ImageLabel") friendStatusLabel.Name = "FriendStatusLabel" friendStatusLabel.Visible = false friendStatusLabel.BackgroundTransparency = 1 friendStatusLabel.Size = UDim2.new(1,0,1,0) friendStatusLabel.Position = UDim2.new(1,0,0,0) friendStatusLabel.Parent = membershipStatusLabel local changeNameFunction local nameLabel = Instance.new("TextLabel") nameLabel.Name = "NameLabel" nameLabel.Text = name nameLabel.Font = Enum.Font.ArialBold nameLabel.FontSize = Enum.FontSize.Size14 nameLabel.TextColor3 = Color3.new(1,1,1) nameLabel.BackgroundTransparency = 1 nameLabel.BackgroundColor3 = Color3.new(0,0,0) nameLabel.TextXAlignment = Enum.TextXAlignment.Left nameLabel, changeNameFunction = RbxGui.AutoTruncateTextObject(nameLabel) nameLabel.Parent = frame updatePlayerName(frame, membershipStatus, teamColor) if supportFriends and not friendRequestBlacklist[game.Players:FindFirstChild(name)] then updatePlayerFriendStatus(frame, friendStatus) else updatePlayerFriendStatus(frame, Enum.FriendStatus.NotFriend) end return frame, changeNameFunction end local function createStatColumn(i, numColumns, isTeam, color3, isHeader, stat) local textLabel = Instance.new("TextButton") textLabel.Name = "Stat" .. i textLabel.AutoButtonColor = false textLabel.TextColor3 = Color3.new(1,1,1) textLabel.TextXAlignment = Enum.TextXAlignment.Right textLabel.TextYAlignment = Enum.TextYAlignment.Center textLabel.FontSize = Enum.FontSize.Size14 if isHeader then textLabel.FontSize = Enum.FontSize.Size18 else textLabel.FontSize = Enum.FontSize.Size14 end if isHeader or isTeam then textLabel.Font = Enum.Font.ArialBold else textLabel.Font = Enum.Font.Arial end if isTeam then textLabel.BackgroundColor3 = color3 textLabel.Text = 0 else textLabel.BackgroundColor3 = Color3.new(0,0,0) textLabel.Text = "" end textLabel.BackgroundTransparency = 1 if i == numColumns then textLabel.Size = UDim2.new(1/numColumns, -6, 1, 0) else textLabel.Size = UDim2.new(1/numColumns, -4, 1, 0) end textLabel.Position = UDim2.new((i-1) * (1/numColumns), 0, 0, 0) local truncLabel, changer = RbxGui.AutoTruncateTextObject(textLabel) if isHeader then local mouseCon = {} mouseCon[1] = truncLabel.MouseEnter:connect(function() truncLabel.BackgroundTransparency = 0.2 end) mouseCon[2] = truncLabel.MouseLeave:connect(function() truncLabel.BackgroundTransparency = 1 end) mouseCon[3] = truncLabel.MouseButton1Click:connect(function() sortPlayerListsFunction(truncLabel:GetChildren()[1].Name, (currentSortName == truncLabel:GetChildren()[1].Name) ) truncLabel.BackgroundTransparency = 1 end) mouseCon[4] = truncLabel:GetChildren()[1].MouseButton1Click:connect(function() sortPlayerListsFunction(textLabel.Name, (currentSortName == truncLabel.Name) ) truncLabel.BackgroundTransparency = 1 end) mouseCon[5] = nil mouseCon[5] = truncLabel.AncestryChanged:connect(function(child,parent) if parent == nil then for i,connection in pairs(mouseCon) do connection:disconnect() end end end) end return truncLabel, changer end local function createStatHeaders(stats, numColumns, isBig) local frame = Instance.new("Frame") frame.Name = "Headers" frame.BorderSizePixel = 0 frame.BackgroundColor3 = Color3.new(0,0,0) frame.BackgroundTransparency = 1 local nameSize if isBig then nameSize = 0.5 elseif numColumns == 1 then nameSize = 0.7 elseif numColumns == 2 then nameSize = 0.6 else nameSize = 0.45 end frame.Size = UDim2.new(1-nameSize, 0, 1,0) if isBig then frame.Position = UDim2.new(nameSize,-25, 0,0) else frame.Position = UDim2.new(nameSize,0, 0,0) end local i = 1 while i <= numColumns do local headerColumn, changeText = createStatColumn(i, numColumns, false, nil, true,stats[i]) changeText(stats[i].Name) headerColumn.Parent = frame i = i + 1 end return frame, textChangers end local function createStatColumns(nameObject, numColumns, isTeam, isBig) local frame = Instance.new("Frame") frame.Name = nameObject.Name .. "_WithStats" frame.BorderSizePixel = 0 frame.BackgroundColor3 = nameObject.BackgroundColor3 frame.BackgroundTransparency = nameObject.BackgroundTransparency frame.Size = nameObject.Size frame.Position = nameObject.Position nameObject.BackgroundTransparency = 1 if numColumns == 0 then nameObject.Size = UDim2.new(1,0,1,0) nameObject.Position = UDim2.new(0,0,0,0) nameObject.Parent = frame return frame end local statFrame = Instance.new("Frame") statFrame.Name = "Stats" if isTeam then statFrame.BorderSizePixel = 0 statFrame.BackgroundColor3 = nameObject.NameLabel.BackgroundColor3 statFrame.BackgroundTransparency = nameObject.NameLabel.BackgroundTransparency else statFrame.BackgroundTransparency = 1 end local nameSize if isBig then nameSize = 0.5 elseif numColumns == 1 then nameSize = 0.7 elseif numColumns == 2 then nameSize = 0.6 else nameSize = 0.45 end nameObject.Size = UDim2.new(nameSize, 0, 1, 0) nameObject.Position = UDim2.new(0, 0, 0, 0) statFrame.Size = UDim2.new(1-nameSize,0, 1,0) statFrame.Position = UDim2.new(nameSize,0, 0,0) nameObject.Parent = frame statFrame.Parent = frame local textChangers = {} local i = 1 while i <= numColumns do local statColumn, changeText = createStatColumn(i, numColumns, isTeam, statFrame.BackgroundColor3) statColumn.Parent = statFrame table.insert(textChangers, changeText) i = i + 1 end return frame, statFrame, textChangers end local function createAlternatingRows(objects) for i, line in ipairs(objects) do if i % 2 == 0 then line.BackgroundTransparency = 1 else line.BackgroundTransparency = 0.95 end end end local removeFromTeam = nil local function clearTableEntry(obj, tableInfo) if tableInfo.MainObjectSmall then tableInfo.MainObjectSmall.Parent = nil tableInfo.MainObjectSmall = nil end if tableInfo.MainObjectBig then tableInfo.MainObjectBig.Parent = nil tableInfo.MainObjectBig = nil end if tableInfo.Connections then for i, connection in ipairs(tableInfo.Connections) do connection:disconnect() end tableInfo.Connections = nil end if tableInfo.LeaderStatConnections then for i, connection in ipairs(tableInfo.LeaderStatConnections) do connection:disconnect() end tableInfo.LeaderStatConnections = nil end if tableInfo.CurrentTeam then removeFromTeam(obj) tableInfo.CurrentTeam = nil end if tableInfo.Players then for i, player in ipairs(tableInfo.Players) do playerTable[player].CurrentTeam = nil end tableInfo.Players = {} end if tableInfo.StatValues then tableInfo.StatValues = nil end end local function resetPlayerTable() for player, info in pairs(playerTable) do clearTableEntry(player, info) playerTable[player] = nil end playerTable = {} end local function resetTeamTable() for team, info in pairs(teamTable) do clearTableEntry(team, info) teamTable[team] = nil end teamTable = {} teamColorTable = {} end local function getBoardTypeInfo() local isTeam = (currentBoardType == "TeamScore" or currentBoardType == "TeamList") local isScore = (currentBoardType == "TeamScore" or currentBoardType == "PlayerScore") return isTeam, isScore end local function recomputeTeamScore(team, column) if not team or team == "Neutral" then return end local function recomputeScoreHelper(statChangers) if statChangers and column <= #statChangers then local sum = 0 for i, p in ipairs(teamTable[team].Players) do if playerTable[p].StatValues and column <= #playerTable[p].StatValues then sum = sum + playerTable[p].StatValues[column].Value end end statChangers[column](sum) end end recomputeScoreHelper(teamTable[team].StatChangersSmall) recomputeScoreHelper(teamTable[team].StatChangersBig) end local function recomputeCompleteTeamScore(team) local col = 1 while col <= currentStatCount do recomputeTeamScore(team, col) col = col + 1 end end removeFromTeam = function(player) if playerTable[player].CurrentTeam ~= nil and teamTable[playerTable[player].CurrentTeam] ~= nil then ArrayRemove(teamTable[playerTable[player].CurrentTeam].Players, player) recomputeCompleteTeamScore(playerTable[player].CurrentTeam) playerTable[player].CurrentTeam = nil end end local function assignToTeam(player) local isTeam, isScore = getBoardTypeInfo() if isTeam then local newTeam = nil if player.Neutral or teamColorTable[player.TeamColor.Name] == nil then newTeam = "Neutral" else newTeam = teamColorTable[player.TeamColor.Name] end if playerTable[player].CurrentTeam == newTeam then return end local oldTeam = playerTable[player].LastTeam removeFromTeam(player) playerTable[player].CurrentTeam = newTeam if teamTable[oldTeam] and teamTable[oldTeam]["NameChangeFuncBig"] then if #teamTable[oldTeam].Players < 1 then teamTable[oldTeam]["NameChangeFuncBig"](" " .. oldTeam.Name) else teamTable[oldTeam]["NameChangeFuncBig"](" " .. oldTeam.Name .. " (" .. tostring(#teamTable[oldTeam].Players) ..")") end end if teamTable[newTeam] then table.insert(teamTable[newTeam].Players, player) if newTeam["Name"] then if teamTable[newTeam]["NameChangeFuncBig"] then if #teamTable[newTeam].Players < 1 then teamTable[newTeam]["NameChangeFuncBig"](" " .. newTeam.Name) else teamTable[newTeam]["NameChangeFuncBig"](" " .. newTeam.Name .. " (" .. tostring(#teamTable[newTeam].Players) ..")") end end end end if newTeam == "Neutral" then updatePlayerNameColor(player, nil) else updatePlayerNameColor(player, player.TeamColor) end playerTable[player].LastTeam = newTeam recomputeCompleteTeamScore(newTeam) --Relayout if sortPlayerListsFunction then sortPlayerListsFunction() end end end local function buildTeamObject(team, numStatColumns, suffix) local isTeam, isScore = getBoardTypeInfo() local teamObject, changeFunc = createTeamName(team.Name, team.TeamColor) teamObject.NameLabel.Text = " " .. team.Name .. " (0)" if not teamTable[team] then teamTable[team] = {} end teamTable[team]["NameObject" .. suffix] = teamObject teamTable[team]["NameChangeFunc" .. suffix] = changeFunc if isScore then local statObject local textChangers teamObject, statObject, textChangers = createStatColumns(teamObject, numStatColumns, true, suffix == "Big") teamTable[team]["StatObject" .. suffix] = statObject teamTable[team]["StatChangers" .. suffix] = textChangers end teamTable[team]["MainObject" .. suffix] = teamObject changeFunc(" " .. team.Name) if not teamTable[team].Players then teamTable[team].Players = {} else if suffix ~= "Small" and #teamTable[team].Players > 0 then changeFunc(" " .. team.Name .. " (" .. tostring(#teamTable[team].Players) ..")") end end return teamObject end local currentContextMenuPlayer = nil local function updatePlayerContextMenu(player,x,y) currentContextMenuPlayer = player local elementHeight = 18 local function highlight(button) button.TextColor3 = Color3.new(0,0,0) button.BackgroundColor3 = Color3.new(0.8,0.8,0.8) end local function clearHighlight(button) button.TextColor3 = Color3.new(1,1,1) button.BackgroundColor3 = Color3.new(0,0,0) end if playerContextMenu == nil then elementNames = {} elementNameToElement = {} for i, contextElement in ipairs(contextMenuElements) do table.insert(elementNames, contextElement.Text) elementNameToElement[tostring(contextElement.Text)] = contextElement end playerContextMenu = Instance.new("TextButton") playerContextMenu.Name = "PlayerListContextMenu" playerContextMenu.Style = Enum.ButtonStyle.RobloxButton playerContextMenu.Text = "" playerContextMenu.Visible = false playerContextMenu.ZIndex = 4 playerContextMenu.MouseLeave:connect(function() local menuChildren = playerContextMenu:GetChildren() for i = 1, #menuChildren do if menuChildren[i].Name == "ChoiceButton" then menuChildren[i].TextColor3 = Color3.new(1,1,1) menuChildren[i].BackgroundTransparency = 1 end end playerContextMenu.Visible = false inContextMenu = false end) playerContextMenu.MouseEnter:connect(function() inContextMenu = true end) for i = 1, #elementNames do local newElementButton = Instance.new("TextButton") newElementButton.Name = "ChoiceButton" newElementButton.Text = elementNames[i] newElementButton.TextColor3 = Color3.new(1,1,1) newElementButton.Font = Enum.Font.Arial newElementButton.FontSize = Enum.FontSize.Size14 newElementButton.BackgroundTransparency = 1 newElementButton.TextWrap = true newElementButton.Size = UDim2.new(1,0,0,elementHeight) newElementButton.Position = UDim2.new(0,0,0,elementHeight * (i - 1)) newElementButton.ZIndex = playerContextMenu.ZIndex + 1 newElementButton.MouseEnter:connect(function() newElementButton.TextColor3 = Color3.new(0,0,0) newElementButton.BackgroundTransparency = 0 end) newElementButton.MouseLeave:connect(function() newElementButton.TextColor3 = Color3.new(1,1,1) newElementButton.BackgroundTransparency = 1 end) newElementButton.MouseButton1Click:connect(function() local element = elementNameToElement[newElementButton.Text] pcall(function() element.DoIt(currentContextMenuPlayer) end) playerContextMenu.Visible = false newElementButton.TextColor3 = Color3.new(1,1,1) newElementButton.BackgroundTransparency = 1 end) newElementButton.Parent = playerContextMenu end robloxLock(playerContextMenu) playerContextMenu.Parent = script.Parent end local visibleElements = 0 for i, contextElement in ipairs(contextMenuElements) do local isVisible = false if contextElement.IsVisible then local success, visible = pcall(function() return contextElement.IsVisible(currentContextMenuPlayer) end) if success then isVisible = visible else print("Error in IsVisible call: " .. visible) end end if isVisible then local foundElement = false for i = 1, #elementNames do if elementNames[i] == contextElement.Text then foundElement = true break end end if not foundElement then table.insert(elementNames,contextElement.Text) end visibleElements = visibleElements + 1 else for i = 1, #elementNames do if elementNames[i] == contextElement.Text then table.remove(elementNames,i) break end end end end playerContextMenu.Size = UDim2.new(0, 150, 0, elementHeight + (elementHeight * visibleElements) ) if x and y then x = x - (playerContextMenu.AbsoluteSize.X/2) if x + playerContextMenu.AbsoluteSize.X >= script.Parent.AbsoluteSize.X then x = script.Parent.AbsoluteSize.X - playerContextMenu.AbsoluteSize.X end playerContextMenu.Position = UDim2.new(0, x, 0, y - 3) end local elementPos = 0 local contextChildren = playerContextMenu:GetChildren() for i = 1, #contextChildren do if contextChildren[i]:IsA("GuiObject") and contextChildren[i].Name == "ChoiceButton" then contextChildren[i].Visible = false for j = 1, #elementNames do if elementNames[j] == contextChildren[i].Text then contextChildren[i].Visible = true contextChildren[i].Position = UDim2.new(0,0,0,elementPos * elementHeight) elementPos = elementPos + 1 break end end end end end local function playerContextMenuHasItems() if playerContextMenu then local children = playerContextMenu:GetChildren() for i = 1, #children do if children[i]:IsA("GuiObject") and children[i].Name == "ChoiceButton" and children[i].Visible then return true end end end return false end local function showPlayerMenu(player, x, y) updatePlayerContextMenu(player,x,y) if not playerContextMenuHasItems() then return end -- don't show if we have nothing to show playerContextMenu.Visible = true end local function buildPlayerObject(player, numStatColumns, suffix) if not player then return nil end local isTeam, isScore = getBoardTypeInfo() local playerObject = nil local changePlayerNameFunction = nil local currentColor = nil if isTeam and not player.Neutral then currentColor = player.TeamColor.Color else currentColor = Color3.new(1,1,1) end playerObject, changePlayerNameFunction = createPlayerName(player.Name, player.MembershipType, currentColor, getFriendStatus(player)) if not playerTable[player] then playerTable[player] = {} end if not playerTable[player].Connections then playerTable[player].Connections = {} end if not playerTable[player].CurrentTeam then playerTable[player].CurrentTeam = nil end if not playerTable[player].LastTeam then playerTable[player].LastTeam = nil end playerTable[player]["NameObject" .. suffix] = playerObject playerTable[player]["ChangeName" .. suffix] = changePlayerNameFunction if isScore then local statObject = nil local textChangers = nil playerObject, statObject, textChangers = createStatColumns(playerObject, numStatColumns, false, suffix == "Big") playerTable[player]["StatObject" .. suffix]= statObject playerTable[player]["StatChangers" .. suffix] = textChangers local statValues, leaderstats = getStatValuesForPlayer(player) if not statValues or #statValues < numStatColumns then if not playerTable[player].LeaderStatConnections then playerTable[player].LeaderStatConnections = {} end --Setup a listener to see when this data gets filled in if not leaderstats then --We don't even have a leaderstats child, wait for one table.insert(playerTable[player].LeaderStatConnections, player.ChildAdded:connect( function(child) if child.Name == "leaderstats" then --Connections will be torn down recreatePlayerFunction(player) else table.insert(playerTable[player].LeaderStatConnections, child.Changed:connect( function(prop) if prop == "Name" and child.Name == "leaderstats" then --Connections will be torn down recreatePlayerFunction(player) end end)) end end)) else --We have a leaderstats, but not enough children, recreate if we get them table.insert(playerTable[player].LeaderStatConnections, leaderstats.ChildAdded:connect( function(child) --TODO only look for IntValue recreatePlayerFunction(player) end) ) table.insert(playerTable[player].LeaderStatConnections, leaderstats.AncestryChanged:connect( function(child) --We got deleted, try again recreatePlayerFunction(player) end) ) end end if statValues then if not playerTable[player].StatValues then playerTable[player].StatValues = {} end local pos = 1 while pos <= numStatColumns and pos <= #statValues do local currentColumn = pos local statValue = statValues[pos] local statChanger = textChangers[pos] local updateStat = function(val) statChanger(val) if playerTable[player] ~= nil then recomputeTeamScore(playerTable[player].CurrentTeam, currentColumn) end end if pos > #playerTable[player].StatValues then table.insert(playerTable[player].StatValues, statValue) end if type(statValue) ~= "number" and statValue["Changed"] then table.insert(playerTable[player].Connections, statValue.Changed:connect(updateStat) ) end table.insert(playerTable[player].Connections, statValue.AncestryChanged:connect( function() recreatePlayerFunction(player) end) ) updateStat(statValue.Value) pos = pos + 1 end end end if supportFriends and player ~= game.Players.LocalPlayer and player.userId > 0 and game.Players.LocalPlayer.userId > 0 then local button = Instance.new("TextButton") button.Name = playerObject.Name .. "Button" button.Text = "" button.Active = false button.Size = playerObject.Size button.Position = playerObject.Position button.BackgroundColor3 = playerObject.BackgroundColor3 local secondButton = Instance.new("TextButton") secondButton.Name = playerObject.Name .. "RealButton" secondButton.Text = "" secondButton.BackgroundTransparency = 1 secondButton.BackgroundColor3 = playerObject.BackgroundColor3 local theNameLabel = playerObject:findFirstChild("NameLabel",true) if theNameLabel then theNameLabel.TextColor3 = Color3.new(1,1,1) secondButton.Parent = theNameLabel end secondButton.Parent.BackgroundTransparency = 1 secondButton.Parent.Visible = true secondButton.ZIndex = 2 secondButton.Size = UDim2.new(1,0,1,0) local previousTransparency = nil table.insert(playerTable[player].Connections, secondButton.MouseEnter:connect( function(x,y) if playerContextMenu and playerContextMenu.Visible then return end -- don't update if we currently see it updatePlayerContextMenu(player,x,y) if not playerContextMenuHasItems() then return end -- don't show if we have nothing to show if previousTransparency == nil then previousTransparency = secondButton.BackgroundTransparency end secondButton.Parent.BackgroundTransparency = 0 end)) table.insert(playerTable[player].Connections, secondButton.MouseLeave:connect( function() if previousTransparency ~= nil then previousTransparency = nil end delay(0.01,function() if playerContextMenu and not inContextMenu then playerContextMenu.Visible = false end end) secondButton.Parent.BackgroundTransparency = 1 end)) local mouseDownX, mouseDownY table.insert(playerTable[player].Connections, secondButton.MouseButton1Down:connect(function(x,y) mouseDownX = x mouseDownY = y end)) table.insert(playerTable[player].Connections, secondButton.MouseButton1Click:connect(function() showPlayerMenu(player, mouseDownX, secondButton.AbsolutePosition.Y + secondButton.AbsoluteSize.Y ) end)) playerObject.BackgroundTransparency = 1 playerObject.Size = UDim2.new(1,0,1,0) playerObject.Position = UDim2.new(0,0,0,0) playerObject.Parent = button playerTable[player]["MainObject" .. suffix] = button playerObject = button else playerTable[player]["MainObject" .. suffix] = playerObject if player == game.Players.LocalPlayer and supportFriends then table.insert(playerTable[player].Connections, player.FriendStatusChanged:connect( function(otherPlayer, friendStatus) if friendRequestBlacklist[otherPlayer] then updatePlayerFriendStatus(playerTable[otherPlayer]["NameObject" .. suffix], Enum.FriendStatus.NotFriend) elseif playerTable[otherPlayer] then updatePlayerFriendStatus(playerTable[otherPlayer]["NameObject" .. suffix], friendStatus) end end) ) end end table.insert(playerTable[player].Connections, player.Changed:connect( function(prop) if prop == "MembershipType" then updatePlayerName(playerTable[player]["NameObject" .. suffix], player.MembershipType, currentColor) elseif prop == "Name" then playerTable[player]["ChangeName" .. suffix](player.Name) elseif prop == "Neutral" or prop == "TeamColor" then assignToTeam(player) end end) ) return playerObject end local function doSort(tableToSort, objectName, order, startPos, sortType, ascending) local orderedPlayerTable = {} getLocalPlayer = false for i, player in ipairs(tableToSort) do if playerTable[player] then if playerTable[player][objectName] ~= nil then if player ~= game.Players.LocalPlayer then table.insert(orderedPlayerTable,playerTable[player][objectName]) else getLocalPlayer = true end end end end if sortType == nil then -- default back to alphabetical sort table.sort(orderedPlayerTable,function(a,b) return string.lower(a:FindFirstChild("FullNameLabel",true).Text) < string.lower(b:FindFirstChild("FullNameLabel",true).Text) end) else -- we are sorting by a value table.sort(orderedPlayerTable,function(a,b) if ascending then currentSortName = "" return tonumber(a:FindFirstChild(sortType,true).Text) > tonumber(b:FindFirstChild(sortType,true).Text) else currentSortName = sortType return tonumber(a:FindFirstChild(sortType,true).Text) < tonumber(b:FindFirstChild(sortType,true).Text) end end) end if getLocalPlayer and playerTable[game.Players.LocalPlayer] and playerTable[game.Players.LocalPlayer][objectName] then table.insert(orderedPlayerTable,1,playerTable[game.Players.LocalPlayer][objectName]) end for i = 1, #orderedPlayerTable do order[orderedPlayerTable[i]] = startPos startPos = startPos + 1 end return startPos end local function orderScrollList(scrollOrder, objectName, scrollFrame, sortType, ascending) local pos = 0 local order = {} local isTeam, isScore = getBoardTypeInfo() for i, obj in ipairs(scrollOrder) do order[obj] = 0 end if isTeam then local teams = getTeams() for i, team in ipairs(teams) do if teamTable[team][objectName] then order[teamTable[team][objectName]] = pos pos = pos + 1 end pos = doSort(teamTable[team].Players, objectName, order, pos, sortType, ascending) end if #teamTable["Neutral"].Players > 0 then teamTable["Neutral"][objectName].Parent = scrollFrame order[teamTable["Neutral"][objectName]] = pos pos = pos + 1 doSort(teamTable["Neutral"].Players, objectName, order, pos, sortType, ascending) else teamTable["Neutral"][objectName].Parent = nil end else local players = getPlayers() doSort(players, objectName, order, pos, sortType, ascending) end table.sort(scrollOrder, function(a,b) return order[a] < order[b] end) end local function createPlayerListBasics(frame, isBig) local headerFrame = Instance.new("Frame") headerFrame.Name = "Header" headerFrame.BackgroundTransparency = 1 headerFrame.Size = UDim2.new(1,-13,0,26) headerFrame.Position = UDim2.new(0,0,0,0) headerFrame.Parent = frame local lowerPaneFrame = Instance.new("Frame") lowerPaneFrame.Name = "ScrollingArea" lowerPaneFrame.BackgroundTransparency = 1 lowerPaneFrame.Size = UDim2.new(1,-3,1,-26) if not isBig then lowerPaneFrame.Size = UDim2.new(1,-3,1,-30) end lowerPaneFrame.Position = UDim2.new(0,0,0,26) lowerPaneFrame.Parent = frame local scrollOrder = {} local scrollFrame, scrollUp, scrollDown, recalculateScroll, scrollBar = RbxGui.CreateScrollingFrame(scrollOrder) scrollBar.Size = UDim2.new(0, 17, 1, -36) if isBig then scrollBar.Size = UDim2.new(0, 17, 1, -61) end scrollBar.Parent = lowerPaneFrame scrollFrame.Parent = lowerPaneFrame scrollUp.Parent = lowerPaneFrame scrollDown.Parent = lowerPaneFrame if isBig then scrollFrame.Position = UDim2.new(0,0,0,0) scrollUp.Position = UDim2.new(1,-41,0,5) scrollDown.Position = UDim2.new(1,-41,1,-35) scrollBar.Position = UDim2.new(1, -41, 0, 24) scrollFrame.Size = UDim2.new(1,-48,1,-16) headerFrame.Size = UDim2.new(1,-20,0,26) else scrollBar.Position = UDim2.new(1, -15, 0, 14) scrollBar.Size = UDim2.new(0,17,1,-36) scrollFrame.Position = UDim2.new(0,1,0,0) scrollUp.Position = UDim2.new(1,-15,0,-5) scrollDown.Position = UDim2.new(1,-15,1,-20) lowerPaneFrame.Position = UDim2.new(0,0,0,30) local toggleScrollBar = function(visible) if visible then scrollFrame.Size = UDim2.new(1,-16,1,0) headerFrame.Size = UDim2.new(1,-16,0,smallWindowHeaderYSize) else scrollFrame.Size = UDim2.new(1,0,1,0) headerFrame.Size = UDim2.new(1,0,0,smallWindowHeaderYSize) end scrollUp.Visible = visible scrollDown.Visible = visible scrollBar.Visible = visible end scrollUp.Changed:connect(function(prop) if prop == "Active" then toggleScrollBar(scrollUp.Active or scrollDown.Active) end end) scrollDown.Changed:connect(function(prop) if prop == "Active" then toggleScrollBar(scrollUp.Active or scrollDown.Active) end end) toggleScrollBar(scrollUp.Active or scrollDown.Active) end return headerFrame, scrollFrame, recalculateScroll, scrollOrder end createBoardsFunction = function (boardType, numStatColumns) local updatePlayerCount = function() return #getPlayers() end local smallFrame = Instance.new("Frame") smallFrame.Name = "SmallPlayerlist" smallFrame.Position = smallWindowPosition smallFrame.Active = false smallFrame.Size = smallWindowSize smallFrame.BackgroundColor3 = Color3.new(0,0,0) smallFrame.BackgroundTransparency = 0.7 smallFrame.BorderSizePixel = 0 local bigFrame = Instance.new("Frame") bigFrame.Name = "BigPlayerlist" bigFrame.Size = bigWindowSize bigFrame.Position = bigWindowPosition bigFrame.BackgroundColor3 = Color3.new(0,0,0) bigFrame.BackgroundTransparency = 0.7 bigFrame.BorderSizePixel = 0 bigFrame.Visible = false local bigFrameWrapper = Instance.new("Frame") bigFrameWrapper.Name = "Expander" bigFrameWrapper.Size = UDim2.new(1,21,1,16) bigFrameWrapper.Position = UDim2.new(0, 0, 0,0) bigFrameWrapper.BackgroundTransparency = 1 bigFrameWrapper.Parent = bigFrame local smallHeaderFrame, scrollFrameSmall, recalculateScrollSmall, scrollOrderSmall = createPlayerListBasics(smallFrame, false) local bigHeaderFrame, scrollFrameBig, recalculateScrollBig, scrollOrderBig = createPlayerListBasics(bigFrameWrapper, true) local playerListButton = Instance.new("ImageButton") playerListButton.Name = "GoBigButton" playerListButton.BackgroundTransparency = 1 playerListButton.Image = "rbxasset://textures/ui/playerlist_small_maximize.png" playerListButton.Size = UDim2.new(0.0, 35, 0, 29) playerListButton.Position = UDim2.new(0, 0, 0, 0) playerListButton.MouseButton1Click:connect( function() toggleBigWindow() end) playerListButton.Parent = smallHeaderFrame playerListButton = Instance.new("ImageButton") playerListButton.Name = "CloseButton" playerListButton.BackgroundTransparency = 1 playerListButton.Image = "rbxasset://textures/ui/playerlist_small_hide.png" playerListButton.Size = UDim2.new(0.0, 38, 0, 29) playerListButton.Position = UDim2.new(0, 35, 0, 0) playerListButton.MouseButton1Click:connect( function() transitionWindowsFunction("None") end) playerListButton.Parent = smallHeaderFrame playerListButton = Instance.new("ImageButton") playerListButton.Name = "CloseButton" playerListButton.Image = "rbxasset://textures/ui/playerlist_big_hide.png" playerListButton.BackgroundTransparency = 1 playerListButton.Size = UDim2.new(0.0, 29, 0, 29) playerListButton.Position = UDim2.new(1, -30, 0.5, -13) playerListButton.MouseButton1Click:connect( function() toggleBigWindow() end) playerListButton.Parent = bigHeaderFrame local placeName = Instance.new("TextButton") placeName.Name = "PlaceName" placeName.Text = " Players (" .. tostring(updatePlayerCount()) .. ")" placeName.AutoButtonColor = false placeName.FontSize = Enum.FontSize.Size24 placeName.TextXAlignment = Enum.TextXAlignment.Left placeName.Font = Enum.Font.ArialBold placeName.BorderSizePixel = 0 placeName.BackgroundColor3 = Color3.new(0,0,0) placeName.BackgroundTransparency = 1 placeName.TextColor3 = Color3.new(1,1,1) placeName.Size = UDim2.new(0.4, 0, 1, 0) placeName.Position = UDim2.new(0, 0, 0.0, 0) placeName = RbxGui.AutoTruncateTextObject(placeName) placeName.Parent = bigHeaderFrame placeName.MouseEnter:connect(function() placeName.BackgroundTransparency = 0.2 end) placeName.MouseLeave:connect(function() placeName.BackgroundTransparency = 1 end) placeName.MouseButton1Click:connect(function() sortPlayerListsFunction() end) currentBoardType = boardType currentStatCount = numStatColumns local isTeam, isScore = getBoardTypeInfo() local players = getPlayers() if isScore then local statColumns = getStatColumns(players) numStatColumns = #statColumns if numStatColumns > 3 then numStatColumns = 3 end createStatHeaders(statColumns, numStatColumns, false).Parent = smallHeaderFrame createStatHeaders(statColumns, currentStatCount, true).Parent = bigHeaderFrame end --Clean up all old stuff resetPlayerTable() updatePlayerCount() for i, player in ipairs(players) do local playerObject = buildPlayerObject(player, numStatColumns, "Small") table.insert(scrollOrderSmall, playerObject) playerObject.Parent = scrollFrameSmall playerObject = buildPlayerObject(player, currentStatCount, "Big") table.insert(scrollOrderBig, playerObject) playerObject.Parent = scrollFrameBig end --Clean up old stuff resetTeamTable() local teamStatObjects = {} if isTeam then local teams = getTeams() local i = #teams while i >= 1 do --We go backwards so the "first" team color gets the team local team = teams[i] teamColorTable[team.TeamColor.Name] = team i = i - 1 end --Adding/Removing a Team causes a full invalidation of the board for i, team in ipairs(teams) do local teamObject = buildTeamObject(team, numStatColumns, "Small") table.insert(scrollOrderSmall, teamObject) teamObject.Parent = scrollFrameSmall teamObject = buildTeamObject(team, currentStatCount, "Big") table.insert(scrollOrderBig, teamObject) teamObject.Parent = scrollFrameBig end teamTable["Neutral"] = {} teamTable["Neutral"].Players = {} local neutralTeamObject = createTeamName("Neutral", BrickColor.palette(8)) teamTable["Neutral"].NameObjectSmall = neutralTeamObject teamTable["Neutral"].StatObjectSmall = nil teamTable["Neutral"].MainObjectSmall = neutralTeamObject table.insert(scrollOrderSmall, neutralTeamObject) neutralTeamObject = createTeamName("Neutral", BrickColor.palette(8)) teamTable["Neutral"].NameObjectBig = neutralTeamObject teamTable["Neutral"].StatObjectBig = nil teamTable["Neutral"].MainObjectBig = neutralTeamObject table.insert(scrollOrderBig, neutralTeamObject) local neutralPlayers = {} for i, player in ipairs(players) do assignToTeam(player) end end removePlayerFunction = function(player) if playerTable[player] then clearTableEntry(player, playerTable[player]) placeName.Text = " Players (" .. tostring(updatePlayerCount()) .. ")" ArrayRemove(scrollOrderSmall, playerTable[player].MainObjectSmall) ArrayRemove(scrollOrderBig, playerTable[player].MainObjectBig) playerTable[player] = nil recalculateSmallPlayerListSize(smallFrame) end end recreatePlayerFunction = function(player) placeName.Text = " Players (" .. tostring(updatePlayerCount()) .. ")" removePlayerFunction(player) local playerObject = buildPlayerObject(player, numStatColumns, "Small") table.insert(scrollOrderSmall, playerObject) robloxLock(playerObject) playerObject.Parent = scrollFrameSmall playerObject = buildPlayerObject(player, currentStatCount, "Big") table.insert(scrollOrderBig, playerObject) robloxLock(playerObject) playerObject.Parent = scrollFrameBig local isTeam, isScore = getBoardTypeInfo() if isTeam then assignToTeam(player) end sortPlayerListsFunction() recalculateSmallPlayerListSize(smallFrame) end if screenResizeCon then screenResizeCon:disconnect() end screenResizeCon = screen.Changed:connect( function(prop) if prop == "AbsoluteSize" then wait() recalculateSmallPlayerListSize(smallFrame) end end) sortPlayerListsFunction = function(sortType, ascending) orderScrollList(scrollOrderSmall, "MainObjectSmall", scrollFrameSmall, sortType, ascending) recalculateScrollSmall() createAlternatingRows(scrollOrderSmall) orderScrollList(scrollOrderBig, "MainObjectBig", scrollFrameBig, sortType, ascending) recalculateScrollBig() createAlternatingRows(scrollOrderBig) end sortPlayerListsFunction() robloxLock(smallFrame) robloxLock(bigFrame) return smallFrame, bigFrame end --Teams changing invalidates the whole board local function teamsChanged() if debounceTeamsChanged then return end debounceTeamsChanged = true wait() rebuildBoard(script.Parent, determineBoardType()) debounceTeamsChanged = false end local checkIfBoardChanged = function() local newBoardType, numStats = determineBoardType() if newBoardType ~= currentBoardType or numStats ~= currentStatCount then rebuildBoard(script.Parent, newBoardType, numStats) end end local function buildPlayerList() waitForChild(game, "Players") waitForProperty(game.Players, "LocalPlayer") local teams = game:GetService("Teams") if teams then local teamConnections = {} teams.ChildAdded:connect( function(child) if child:IsA("Team") then teamsChanged() teamConnections[child] = child.Changed:connect( function(prop) if prop == "TeamColor" or prop == "Name" then --Rebuild when things change teamsChanged() end end) end end) teams.ChildRemoved:connect( function(child) if child:IsA("Team") then if teamConnections[child] then teamConnections[child]:disconnect() teamConnections[child] = nil end teamsChanged() end end) end game.Players.ChildAdded:connect( function(player) if player:IsA("Player") then addPlayerFunction(player) end end) game.Players.ChildRemoved:connect( function(player) if player:IsA("Player") then if removePlayerFunction then removePlayerFunction(player) end end end) rebuildBoard(script.Parent, determineBoardType()) game.GuiService:AddKey("\t") local lastTime = nil game.GuiService.KeyPressed:connect( function(key) if key == "\t" then local modalCheck, isModal = pcall(function() return game.GuiService.IsModalDialog end) if modalCheck == false or (modalCheck and isModal == false) then local currentTime = time() if lastTime == nil or currentTime - lastTime > 0.4 then lastTime = currentTime toggleBigWindow() end end end end) delay(0, function() while true do wait(5) checkIfBoardChanged() end end) end buildPlayerList() if not personalServerPlace then -- one more backup check local theBool = game.Workspace:FindFirstChild("PSVariable") if theBool and theBool:IsA("BoolValue") then personalServerPlace = true end end if personalServerPlace then addPersonalServerContext() setupBuildToolManagement() else local psVarCon = nil psVarCon = game.Workspace.ChildAdded:connect(function(child) if child:IsA("BoolValue") and child.Name == "PSVariable" then psVarCon:disconnect() personalServerPlace = true addPersonalServerContext() setupBuildToolManagement() end end) end ---------------------------------- Start Player Hover Code ---------------------------------------- if contextMenu3d then local inMenu = false function waitForProperty(instance, name) while not instance[name] do instance.Changed:wait() end end function makeNewActionButton() local button = Instance.new("TextButton") button.Name = "ActionButton" button.Style = Enum.ButtonStyle.RobloxButtonDefault button.BackgroundColor3 = Color3.new(0,0,0) button.BorderColor3 = Color3.new(1,0,0) button.BackgroundTransparency = 0.5 button.Size = UDim2.new(1,0,0,50) button.Text = "" button.Font = Enum.Font.ArialBold button.FontSize = Enum.FontSize.Size18 button.TextColor3 = Color3.new(1,1,1) button.ZIndex = 4 return button end function getContextElements(currentContextMenuPlayer) local elements = {} for i, contextElement in ipairs(contextMenuElements) do local element = contextElement local isVisible = false if contextElement.IsVisible then local success, visible = pcall(function() return contextElement.IsVisible(currentContextMenuPlayer) end) if success then isVisible = visible else print("Error in IsVisible call: " .. visible) end end if element.Type == "Button" then local button = makeNewActionButton() button.Name = "ContextButton" .. i button.Visible = isVisible button.Text = contextElement.Text button.MouseButton1Click:connect(function() if button.Active then local success, result = pcall(function() element.DoIt(currentContextMenuPlayer) end) end end) contextElement.Button = button contextElement.Element = button table.insert(elements,contextElement) end end return elements end function findContextElement(contextElements, button) for i = 1, #contextElements do if contextElements[i].Button == button then return contextElements[i] end end end function populateActions(scrollFrame, nullFrame, recalcFunction, otherPlayer) local elements = getContextElements(otherPlayer) for i = 1, #elements do if elements[i].Button.Visible then elements[i].Button.Parent = scrollFrame else elements[i].Button.Parent = nullFrame end local actionButtonCon actionButtonCon = elements[i].Button.MouseButton1Click:connect(function() actionButtonCon:disconnect() local nullFrameChildren = nullFrame:GetChildren() for j = 1, #nullFrameChildren do local contextElement = findContextElement(elements, nullFrameChildren[j]) pcall(function() nullFrameChildren[j].Visible = contextElement.IsVisible(otherPlayer) end) if nullFrameChildren[j].Visible then nullFrameChildren[j].Parent = scrollFrame end end local scrollFrameChildren = scrollFrame:GetChildren() for j = 1, #scrollFrameChildren do local contextElement = findContextElement(elements, scrollFrameChildren[j]) pcall(function() scrollFrameChildren[j].Visible = contextElement.IsVisible(otherPlayer) end) if not scrollFrameChildren[j].Visible then scrollFrameChildren[j].Parent = nullFrame end end elements[i].Button.Parent = nullFrame recalcFunction() end) end end function createContextMenu(otherPlayer) local frame = Instance.new("Frame") frame.Name = "ContextMenuFrame" frame.Style = Enum.FrameStyle.RobloxRound frame.Size = UDim2.new(0,300,0,400) frame.Position = UDim2.new(0.5,-150,0.5,-200) frame.ZIndex = 2 local scrollFrame, scrollUpButton, scrollDownButton, recalc, scrollBar = RbxGui.CreateScrollingFrame() scrollFrame.Name = "Actions" scrollFrame.BackgroundTransparency = 1 scrollFrame.Position = UDim2.new(0,0,0,25) scrollFrame.Size = UDim2.new(1,-20,1,-80) scrollFrame.ZIndex = 3 scrollFrame.Parent = frame local nullFrame = Instance.new("Frame") nullFrame.Name = "NullFrame" nullFrame.BackgroundTransparency = 1 nullFrame.Visible = false nullFrame.Parent = frame local scrollButtons = Instance.new("Frame") scrollButtons.Name = "ScrollButtons" scrollButtons.BackgroundTransparency = 1 scrollButtons.Position = UDim2.new(1,-17,0,25) scrollButtons.Size = UDim2.new(0,17,1,-80) scrollButtons.ZIndex = 3 scrollButtons.Parent = frame scrollUpButton.ZIndex = 3 scrollUpButton.Parent = scrollButtons scrollDownButton.Position = UDim2.new(0,0,1,-17) scrollDownButton.ZIndex = 3 scrollDownButton.Parent = scrollButtons scrollBar.Size = UDim2.new(1,0,1,-34) scrollBar.Position = UDim2.new(0,0,0,17) scrollBar.Parent = scrollButtons local playerImage = Instance.new("ImageLabel") playerImage.Name = "PlayerImage" playerImage.BackgroundTransparency = 1 playerImage.Image = "http://www.roblox.com/thumbs/avatar.ashx?userId=" .. tostring(otherPlayer.userId) .. "&x=352&y=352" playerImage.Position = UDim2.new(0.5,-150,0.5,-150) playerImage.Size = UDim2.new(0,300,0,300) playerImage.Parent = frame local playerName = Instance.new("TextLabel") playerName.Name = "PlayerName" playerName.BackgroundTransparency = 1 playerName.Font = Enum.Font.ArialBold playerName.FontSize = Enum.FontSize.Size24 playerName.Position = UDim2.new(0,-8,0,-6) playerName.Size = UDim2.new(1,16,0,24) playerName.Text = otherPlayer["Name"] playerName.TextColor3 = Color3.new(1,1,1) playerName.TextWrap = true playerName.ZIndex = 3 playerName.Parent = frame local doneButtonCon local doneButton = Instance.new("TextButton") doneButton.Name = "DoneButton" doneButton.Style = Enum.ButtonStyle.RobloxButton doneButton.Font = Enum.Font.ArialBold doneButton.FontSize = Enum.FontSize.Size36 doneButton.Position = UDim2.new(0.25,0,1,-50) doneButton.Size = UDim2.new(0.5,0,0,50) doneButton.Text = "Done" doneButton.TextColor3 = Color3.new(1,1,1) doneButton.ZIndex = 3 doneButton.Parent = frame doneButton.Modal = true doneButtonCon = doneButton.MouseButton1Click:connect(function() doneButtonCon:disconnect() inMenu = false game.GuiService:RemoveCenterDialog(frame) frame:remove() end) populateActions(scrollFrame, nullFrame, recalc, otherPlayer) recalc() return frame end function makeContextInvisible(menu) menu.Visible = false end function goToContextMenu(otherPlayer) local menu = createContextMenu(otherPlayer) game.GuiService:AddCenterDialog(menu, Enum.CenterDialogType.PlayerInitiatedDialog, --ShowFunction function() menu.Visible = true menu:TweenSize(UDim2.new(0,300,0,400),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,0.5,true) end, --HideFunction function() menu:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,0.5,true,function() makeContextInvisible(menu) end) end) menu.Parent = script.Parent if menu.Visible == true then inMenu = true elseif menu.Visible == false then inMenu = false end end waitForProperty(game.Players, "LocalPlayer") local currSelectedPlayer = nil if game.Players.LocalPlayer["HoverOnPlayerChanged"] then game.Players.LocalPlayer.HoverOnPlayerChanged:connect(function(otherPlayer) if not inMenu then if otherPlayer and otherPlayer.userId < 0 then return end -- we don't want this for guests end wait(0.5) currSelectedPlayer = otherPlayer end) end if game.Players.LocalPlayer["MouseDownOnPlayer"] then game.Players.LocalPlayer.MouseDownOnPlayer:connect(function(otherPlayer) if currSelectedPlayer ~= otherPlayer then return end if not inMenu and otherPlayer.userId > 0 then goToContextMenu(otherPlayer) end end) end end end ---------------------------------- End Player Hover Code ---------------------------------------- Backpack false BackpackBuilder --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 -- 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 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, -170, 1, -85) CurrentLoadout.Size = UDim2.new(0, 480, 0, 48) CurrentLoadout.BackgroundTransparency = 1 CurrentLoadout.Parent = gui local Debounce = Instance.new("BoolValue") Debounce.Name = "Debounce" Debounce.Parent = CurrentLoadout for i = 0, 9 do local slotFrame = Instance.new("Frame") slotFrame.BackgroundColor3 = Color3.new(0,0,0) slotFrame.BackgroundTransparency = 1 slotFrame.BorderColor3 = Color3.new(1,1,1) slotFrame.Name = "Slot" .. tostring(i) if i == 0 then slotFrame.Position = UDim2.new(0.9,0,0,0) else slotFrame.Position = UDim2.new((i - 1) * 0.1,0,0,0) end slotFrame.Size = UDim2.new(0.1,0,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.Style = Enum.ButtonStyle.RobloxButton TempSlot.Visible = false TempSlot.Parent = CurrentLoadout -- TempSlot Children local GearReference = Instance.new("ObjectValue") GearReference.Name = "GearReference" GearReference.Parent = TempSlot local ToolTipLabel = Instance.new("TextLabel") ToolTipLabel.Name = "ToolTipLabel" 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.Parent = TempSlot local GearImage = Instance.new("ImageLabel") GearImage.Name = "GearImage" GearImage.BackgroundTransparency = 1 GearImage.Position = UDim2.new(0,-7,0,-7) GearImage.Size = UDim2.new(1,14,1,14) GearImage.ZIndex = 2 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,-7,0,-7) 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.ZIndex = 4 SlotNumber.Parent = TempSlot local SlotNumberDownShadow = SlotNumber:clone() SlotNumberDownShadow.Name = "SlotNumberDownShadow" SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0) SlotNumberDownShadow.ZIndex = 3 SlotNumberDownShadow.Position = UDim2.new(0,-6,0,-6) SlotNumberDownShadow.Parent = TempSlot local SlotNumberUpShadow = SlotNumberDownShadow:clone() SlotNumberUpShadow.Name = "SlotNumberUpShadow" SlotNumberUpShadow.Position = UDim2.new(0,-8,0,-8) SlotNumberUpShadow.Parent = TempSlot local GearText = Instance.new("TextLabel") 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.ZIndex = 2 GearText.Size = UDim2.new(1,16,1,16) GearText.Text = "" GearText.TextColor3 = Color3.new(1,1,1) GearText.TextWrap = true GearText.Parent = TempSlot --- Great, now lets make the inventory! local Backpack = Instance.new("Frame") Backpack.Visible = false Backpack.Name = "Backpack" Backpack.Position = UDim2.new(0.5,0,0.5,0) Backpack.BackgroundColor3 = Color3.new(0,0,0) Backpack.BackgroundTransparency = 0.08 Backpack.BorderSizePixel = 0 Backpack.Parent = gui Backpack.Active = true -- Backpack Children local SwapSlot = Instance.new("BoolValue") SwapSlot.Name = "SwapSlot" SwapSlot.Parent = Backpack -- SwapSlot Children local Slot = Instance.new("IntValue") Slot.Name = "Slot" Slot.Parent = SwapSlot local GearButton = Instance.new("ObjectValue") GearButton.Name = "GearButton" GearButton.Parent = SwapSlot local Tabs = Instance.new("Frame") Tabs.Name = "Tabs" Tabs.Visible = 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.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.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.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.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.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.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.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.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.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.BackgroundTransparency = 1 Gear.Size = UDim2.new(1,0,1,0) Gear.Parent = Backpack -- Gear Children local AssetsList = Instance.new("Frame") 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.Name = "GearGrid" GearGrid.Size = UDim2.new(0.69,0,1,0) GearGrid.BackgroundTransparency = 1 GearGrid.Parent = Gear local GearButton = Instance.new("ImageButton") GearButton.Visible = false GearButton.Name = "GearButton" GearButton.Size = UDim2.new(0,64,0,64) GearButton.Style = Enum.ButtonStyle.RobloxButton GearButton.Parent = GearGrid -- GearButton Children local GearReference = Instance.new("ObjectValue") GearReference.Name = "GearReference" GearReference.Parent = GearButton local GreyOutButton = Instance.new("Frame") 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.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.Name = "GearGridScrollingArea" GearGridScrollingArea.Position = UDim2.new(0.7,0,0,35) GearGridScrollingArea.Size = UDim2.new(0,17,1,-45) GearGridScrollingArea.BackgroundTransparency = 1 GearGridScrollingArea.Parent = Gear local GearLoadouts = Instance.new("Frame") 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.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.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 ------------------------------- WARDROBE ------------------------------------------------------- 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 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 t.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 t.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%S02sfJuSM3Thz5hVIxyf9kDDENER9guz5nwJx/SfET0qAar5EDNQ6VJkwq7L45ZNfqVNd7IxhujzkgYff2V8ee5Mp5MfS9aEcztYGlWumULivAzynGfqkdVh+GzofuzUmMwWqPPsKqvQLiFe9MXMtCqe89S/Y9n6LZgrS1hyuqY=% --fixed by iagoMAO -- -- 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 closeButton = backpack.Tabs.CloseButton 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 waitForChild(player,"Backpack") local playerBackpack = player.Backpack waitForChild(backpack,"Gear") waitForChild(backpack.Gear,"GearPreview") local gearPreview = backpack.Gear.GearPreview waitForChild(backpack.Gear,"GearGridScrollingArea") local scroller = backpack.Gear.GearGridScrollingArea waitForChild(backpack.Parent,"CurrentLoadout") local currentLoadout = backpack.Parent.CurrentLoadout waitForChild(backpack.Parent,"ControlFrame") waitForChild(backpack.Parent.ControlFrame,"BackpackButton") local backpackButton = backpack.Parent.ControlFrame.BackpackButton waitForChild(backpack.Gear,"GearGrid") waitForChild(backpack.Gear.GearGrid,"GearButton") local gearButton = backpack.Gear.GearGrid.GearButton local grid = backpack.Gear.GearGrid waitForChild(backpack.Gear.GearGrid,"SearchFrame") waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchBoxFrame") waitForChild(backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame,"SearchBox") local searchBox = backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame.SearchBox waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchButton") local searchButton = backpack.Gear.GearGrid.SearchFrame.SearchButton waitForChild(backpack.Gear.GearGrid,"ResetFrame") local resetFrame = backpack.Gear.GearGrid.ResetFrame waitForChild(backpack.Gear.GearGrid.ResetFrame,"ResetButtonBorder") local resetButton = backpack.Gear.GearGrid.ResetFrame.ResetButtonBorder waitForChild(script.Parent,"SwapSlot") local swapSlot = script.Parent.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.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 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 = visible 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) 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 pcall(function() closeButton.Modal = true end) closeButton.MouseButton1Click:connect(function() openCloseBackpack() 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 recalculateScrollLoadout() print("Backpack has been built. Time for the resizer script.") script.Parent.BackpackResizer.Parent = script.Parent.Backpack false BackpackScript -- 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 local currentLoadout = script.Parent local maxNumLoadoutItems = 10 local guiBackpack = currentLoadout.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 = {} --- 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 centerGear() local Loadout = script.Parent.CurrentLoadout Loadout.Position = UDim2.new(0.45, -170, 1, -85) loadoutChildren = Loadout:GetChildren() local gearButtons = {} local lastSlotAdd = nil for i = 1,#loadoutChildren do if loadoutChildren[i]:IsA("Frame") then if #loadoutChildren[i]:GetChildren() > 0 then if loadoutChildren[i].Name == "Slot0" then lastSlotAdd = loadoutChildren[i] else table.insert(gearButtons,loadoutChildren[i]) end end loadoutChildren[i].BackgroundTransparency = 1 if script.Parent.Backpack.Visible == true then loadoutChildren[i].BackgroundTransparency = 0.5 elseif script.Parent.Backpack.Visible == false then loadoutChildren[i].BackgroundTransparency = 1 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 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" delay(guiTweenSpeed/2, function() gear:remove() if script.Parent.Backpack.Visible == false then centerGear() else gear:remove() end 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 if script.Parent.Backpack.Visible == false then centerGear() else return end 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.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]) return true end end end if x < frame.AbsolutePosition.x or x > ( frame.AbsolutePosition.x + frame.AbsoluteSize.x ) then reorganizeLoadout(gearClone,false) return false elseif y < frame.AbsolutePosition.y or y > ( frame.AbsolutePosition.y + frame.AbsoluteSize.y ) then reorganizeLoadout(gearClone,false) return false else gearClone.Position = dragBeginPos return -1 end end function unequipAllItems(dontEquipThis) for i = 1, #gearSlots do if gearSlots[i] == "empty" then break end if 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 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.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 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 print("no slots!") return end -- No available slot to add in! local slotNum = slotToMod % 10 local parent = currentLoadout.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.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.CurrentLoadout.Visible = false end function setupBackpackListener() if backpackChildCon then backpackChildCon:disconnect() end backpackChildCon = player.Backpack.ChildAdded:connect(function(child) addingPlayerChild(child) addToInventory(child) end) end function playerCharacterChildAdded(child) addingPlayerChild(child,true) addToInventory(child) 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) 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() deactivateLoadout() end) player.CharacterRemoving:connect(function() if characterChildAddedCon then characterChildAddedCon:disconnect() end if humanoidDiedCon then humanoidDiedCon:disconnect() end if backpackChildCon then backpackChildCon:disconnect() end deactivateLoadout() end) player.CharacterAdded:connect(function() player = game.Players.LocalPlayer -- make sure we are still looking at the correct character for i = 1, #gearSlots do if gearSlots[i] ~= "empty" then gearSlots[i].Parent = nil gearSlots[i] = "empty" end end local backpackChildren = player.Backpack:GetChildren() local size = math.min(10,#backpackChildren) for i = 1, size do addingPlayerChild(backpackChildren[i]) end setupBackpackListener() characterChildAddedCon = player.Character.ChildAdded:connect(function(child) addingPlayerChild(child,true) end) waitForChild(player.Character,"Humanoid") humanoidDiedCon = player.Character.Humanoid.Died:connect(function() deactivateLoadout() end) activateLoadout() end) script.Parent.ControlFrame.BackpackButton.MouseButton1Click:connect(function() centerGear() 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) end guiBackpack.SwapSlot.Value = false end end) keyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) activateGear(key) end) 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 BackpackMaker local BackpackButton = Instance.new("ImageButton") BackpackButton.Visible = true BackpackButton.Name = "BackpackButton" BackpackButton.BackgroundTransparency = 1 BackpackButton.Image = "rbxasset://textures/ui/backpackButton.png" BackpackButton.Position = UDim2.new(0.5, -195, 1, -30) BackpackButton.Size = UDim2.new(0,107,0,26) BackpackButton.Parent = script.Parent.ControlFrame -- this makes the backpackbutton without making the backpack D I E -- false BackpackManager -- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search) print("mamanger") print("made it past gui version check") -- 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, "Tabs") waitForChild(backpack.Tabs, "CloseButton") local closeButton = backpack.Tabs.CloseButton waitForChild(backpack.Tabs, "InventoryButton") local inventoryButton = backpack.Tabs.InventoryButton 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 canToggle = true local readyForNextEvent = true local backpackIsOpen = false local active = true local humanoidDiedCon = nil local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack local searchDefaultText = "Search..." local tilde = "~" local backquote = "`" ------------------------ 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 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 function resizeGrid() local backpackItems = {} 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) else buttonClone.Position = beginPos end end end) mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end) mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() buttonClick(buttonClone) end) end end 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 resize() local size = 0 local gearPreview = script.Parent.Backpack.Gear.GearPreview 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 openCloseBackpack() if backpack.Visible == true then updateGridActive() loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then loadoutChildren[i].BackgroundTransparency = 0.5 end end spreadOutGear(loadoutChildren) --[[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 end function centerGear() local Loadout = script.Parent.CurrentLoadout Loadout.Position = UDim2.new(0.45, -170, 1, -85) loadoutChildren = Loadout:GetChildren() local gearButtons = {} local lastSlotAdd = nil for i = 1,#loadoutChildren do if loadoutChildren[i]:IsA("Frame") then if #loadoutChildren[i]:GetChildren() > 0 then if loadoutChildren[i].Name == "Slot0" then lastSlotAdd = loadoutChildren[i] else table.insert(gearButtons,loadoutChildren[i]) end end loadoutChildren[i].BackgroundTransparency = 1 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 local hideBackpack = function() backpackIsOpen = false readyForNextEvent = false backpackButton.Selected = false resetSearch() backpackCloseEvent:Fire(currentTab) backpack.Tabs.Visible = false searchFrame.Visible = false loadoutChildren = script.Parent.CurrentLoadout:GetChildren() for i = 1,#loadoutChildren do if loadoutChildren[i]:IsA("Frame") then if #loadoutChildren[i]:GetChildren() > 0 then if loadoutChildren[i].Name == "Slot0" then lastSlotAdd = loadoutChildren[i] end end loadoutChildren[i].BackgroundTransparency = 1 centerGear() end backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), 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 canToggle = 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 backpackButton.Selected = true backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.76, 0),UDim2.new(0.225, 0, 0.09, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true) delay(guiTweenSpeed,function() openCloseBackpack() backpack.Tabs.Visible = true searchFrame.Visible = true backpackOpenEvent:Fire(currentTab) 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 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 showBackpack() else backpackButton.Selected = false closeBackpack() end end function updateGridActive() local backpackItems = {} 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 openCloseBackpack() if backpack.Visible == true then updateGridActive() local currentLoadout = script.Parent.CurrentLoadout 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) 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 = visible resizeGrid() resize() pcall(function() game.GuiService:RemoveCenterDialog(backpack) end) openCloseDebounce = false 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 setSelected(inventoryButton) setUnselected(wardrobeButton) elseif selectedTab == "wardrobe" then setSelected(wardrobeButton) setUnselected(inventoryButton) 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 ------------------------------------------- inventoryButton.MouseButton1Click:connect(function() newTabClicked("gear") end) inventoryButton.MouseEnter:connect(function() mouseOverTab(inventoryButton) end) inventoryButton.MouseLeave:connect(function() mouseLeaveTab(inventoryButton) end) closeButton.MouseButton1Click:connect(hideBackpack) screen.Changed:connect(function(prop) if prop == "AbsoluteSize" then resizeEvent:Fire(screen.AbsoluteSize) end end) -- GuiService key setup local testkey = "'" game:GetService("GuiService"):AddKey(testkey) game:GetService("GuiService"):AddKey(tilde) 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() toggleBackpack() showBackpack() --openCloseBackpack() 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 BackpackGear 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 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 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,"Tabs") 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") 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.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) buttonClone.ZIndex = 1 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 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 = 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 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 BackpackResizer print("Making sure BackpackResizer script is doing it's work...") print("Backpack has been built. Time for the resizer script.") script.Parent.BackpackResizer.Parent = script.Parent.Backpack 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 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 --rbxsig%mno74b/wRJKHL8Xt9/BxwXVZl+tc9a/CmKlTTsWwuH0ibb5lbU57AjhmG/j/sFf+k7yKL9GKKWCUdPSSH3I6N4Vg02Ru5DtokfUAKrgAAdixtQU0mSgGT3ZI/vNZjH7Dw39RzLgT4rVVyCh38B/pVg0BKcE3SdIXVdeIRPX0cb8=% --rbxassetid%53878053% -- 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 local screen = script.Parent.Parent local openCloseDebounce = false local backpackItems = {} local buttons = {} local debounce = false local guiTweenSpeed = 1 local backpackOldStateVisible = false 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 currentLoadout = backpack.Parent.CurrentLoadout local swapSlot = script.Parent.SwapSlot local grid = script.Parent.Gear.GearGrid local scroller = backpack.Gear.GearGridScrollingArea local gearPreview = backpack.Gear.GearPreview local playerBackpack = player.Backpack local currentLoadout = backpack.Parent.CurrentLoadout local backpackButton = backpack.Parent.ControlFrame.BackpackButton local gearButton = backpack.Gear.GearGrid.GearButton local searchBox = backpack.SearchFrame.SearchBoxFrame.SearchBox local searchButton = backpack.SearchFrame.SearchButton local gearPreview = backpack.Gear.GearPreview local resetButton = backpack.SearchFrame.ResetButton -- 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 = grid 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 = script.Parent.Gear.GearLoadouts.GearLoadoutsScrollingArea scrollDownLoadout.Parent = script.Parent.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 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 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) else buttonClone.Position = beginPos end end end) mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end) mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() buttonClick(buttonClone) end) end end end recalculateScroll() end function showPartialGrid(subset) 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() 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() if backpack.Visible == true then updateGridActive() loadoutChildren = currentLoadout:GetChildren() for i = 1, #loadoutChildren do if loadoutChildren[i]:IsA("Frame") then loadoutChildren[i].BackgroundTransparency = 0.5 end end spreadOutGear(loadoutChildren) --[[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 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") 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() backpack.Visible = backpackOldStateVisible 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 backpackOldStateVisible = backpack.Visible backpack.Visible = false 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() 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 searchBox = backpack.SearchFrame.SearchBoxFrame.SearchBox 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) 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) ------------------------- 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 -- 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 backpackButton.Visible = true recalculateScrollLoadout() false Workaround wait(0.1) game.Players.LocalPlayer.PlayerGui.Backpack.BackpackResizer.Disabled = true game.Players.LocalPlayer.PlayerGui.Backpack.BackpackResizer.Disabled = false game.Players.LocalPlayer.PlayerGui.Backpack.CurrentLoadout.Visible = true