null
nil
-
false
Sorter
print("Special thanks to Bitl, Carrot, iago, winsupermario1234, Khangaroo, drslicendice, coke, TheLivingBee, Raymonf, and a bunch of play - testers for help making 2012 fully stable and work. 8)")
script.Playerlist:clone().Parent = game.StarterGui
script.Dialogs:clone().Parent = game.StarterGui
script.Backpack:clone().Parent = game.StarterGui
script.Health:clone().Parent = game.StarterGui
script.Menu:clone().Parent = game.StarterGui
script.ReenableDialogScript:clone().Parent = game.Lighting
script.TimeoutScript:clone().Parent = game.Lighting
script.ResetCommand:clone().Parent = game.Workspace
script.Chat:clone().Parent = game.StarterGui
script.Notifications.Parent = game.StarterGui
script:remove()
-
Backpack
-
false
4288914085
1
4279970357
1
false
false
ControlFrame
0
0
0
0
1
0
1
0
0
0
true
1
-
false
4288914085
1
4279970357
1
false
false
NotificationBox
1
-200
0.5
0
0
200
0.419999987
0
0
true
1
-
false
BackpackBuilder
-- fixed by iagoMAO#6808, any bugs report to me. --
--rbxsig%ajqqTypn8cXmAlrdqhDKhItl413ndYEkpVdn/u7NGTmEyfwlhOJeSdZIZE+QLG/vRLkbVlp75MyPeWt7MR7K443uOfLnmRnXvj0XdhY0HQxdqVu9uRh1FvpjhLVWE3p9GRv2Vh99QxI/FUC0rDcT64cNueM8fjBp7QpFypJ1R+8=%
--rbxassetid%53878047%
-- This script creates almost all gui elements found in the backpack (warning: there are a lot!)
-- TODO: automate this process
local gui = script.Parent
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
local function IsTouchDevice()
-- local touchEnabled = false
-- pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end)
-- return touchEnabled
end
local function IsPhone()
--if gui.AbsoluteSize.Y <= 320 then
--- return true
-- end
-- return false
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
-- First up is the current loadout
local CurrentLoadout = Instance.new("Frame")
CurrentLoadout.Name = "CurrentLoadout"
CurrentLoadout.Position = UDim2.new(0.5, -300, 1, -85)
CurrentLoadout.Size = UDim2.new(0, 600, 0, 54)
CurrentLoadout.BackgroundTransparency = 1
--CurrentLoadout.RobloxLocked = true
CurrentLoadout.Parent = gui
local CLBackground = Instance.new('ImageLabel')
CLBackground.Name = 'Background';
CLBackground.Size = UDim2.new(1.2, 0, 1.2, 0);
CLBackground.Image = "http://www.roblox.com/asset/?id=96536002"
CLBackground.BackgroundTransparency = 1.0;
CLBackground.Position = UDim2.new(-0.1, 0, -0.1, 0);
CLBackground.ZIndex = 0.0;
CLBackground.Parent = CurrentLoadout
CLBackground.Visible = true
local BackgroundUp = Instance.new('ImageLabel')
BackgroundUp.Size = UDim2.new(1, 0, 0.025, 1)
BackgroundUp.Position = UDim2.new(0, 0, 0, 0)
BackgroundUp.Image = 'http://www.roblox.com/asset/?id=97662207'
BackgroundUp.BackgroundTransparency = 1.0
BackgroundUp.Parent = CLBackground
local Debounce = Instance.new("BoolValue")
Debounce.Name = "Debounce"
--Debounce.RobloxLocked = true
Debounce.Parent = CurrentLoadout
local BackpackButton = Instance.new("ImageButton")
--BackpackButton.RobloxLocked = true
BackpackButton.Visible = true
BackpackButton.Name = "BackpackButton"
BackpackButton.BackgroundTransparency = 1
BackpackButton.Image = "http://www.roblox.com/asset/?id=97617958"
BackpackButton.Position = UDim2.new(0.5, -60, 1, -108)
BackpackButton.Size = UDim2.new(0, 120, 0, 18)
waitForChild(gui,"ControlFrame")
BackpackButton.Parent = gui.ControlFrame
local NumSlots = 9
for i = 0, NumSlots do
local slotFrame = Instance.new("Frame")
-- slotFrame.RobloxLocked = true
slotFrame.BackgroundColor3 = Color3.new(0,0,0)
slotFrame.BackgroundTransparency = 1
slotFrame.BorderColor3 = Color3.new(1, 1, 1)
slotFrame.Name = "Slot" .. tostring(i)
slotFrame.ZIndex = 4.0
if i == 0 then
slotFrame.Position = UDim2.new(0.9, 0, 0, 0)
else
slotFrame.Position = UDim2.new((i - 1) * 0.1, (i-1)* 6,0,0)
end
slotFrame.Size = UDim2.new(0, 54, 1, 0)
slotFrame.Parent = CurrentLoadout
end
local TempSlot = Instance.new("ImageButton")
TempSlot.Name = "TempSlot"
TempSlot.Active = true
TempSlot.Size = UDim2.new(1,0,1,0)
TempSlot.BackgroundTransparency = 1.0
TempSlot.Style = 'Custom'
TempSlot.Visible = false
--TempSlot.RobloxLocked = true
TempSlot.Parent = CurrentLoadout
TempSlot.ZIndex = 4.0
local slotBackground = Instance.new('ImageLabel')
slotBackground.Name = 'Background'
slotBackground.BackgroundTransparency = 1.0
slotBackground.Image = 'http://www.roblox.com/asset/?id=97613075'
slotBackground.Size = UDim2.new(1, 0, 1, 0)
slotBackground.Parent = TempSlot
local HighLight = Instance.new('ImageLabel')
HighLight.Name = 'Highlight'
HighLight.BackgroundTransparency = 1.0
HighLight.Image = 'http://www.roblox.com/asset/?id=97643886'
HighLight.Size = UDim2.new(1, 0, 1, 0)
--HighLight.Parent = TempSlot
HighLight.Visible = false
-- TempSlot Children
local GearReference = Instance.new("ObjectValue")
GearReference.Name = "GearReference"
--GearReference.RobloxLocked = true
GearReference.Parent = TempSlot
local ToolTipLabel = Instance.new("TextLabel")
ToolTipLabel.Name = "ToolTipLabel"
-- ToolTipLabel.RobloxLocked = true
ToolTipLabel.Text = ""
ToolTipLabel.BackgroundTransparency = 0.5
ToolTipLabel.BorderSizePixel = 0
ToolTipLabel.Visible = false
ToolTipLabel.TextColor3 = Color3.new(1,1,1)
ToolTipLabel.BackgroundColor3 = Color3.new(0,0,0)
ToolTipLabel.TextStrokeTransparency = 0
ToolTipLabel.Font = Enum.Font.ArialBold
ToolTipLabel.FontSize = Enum.FontSize.Size14
--ToolTipLabel.TextWrap = true
ToolTipLabel.Size = UDim2.new(1,60,0,20)
ToolTipLabel.Position = UDim2.new(0,-30,0,-30)
ToolTipLabel.Parent = TempSlot
local Kill = Instance.new("BoolValue")
Kill.Name = "Kill"
-- Kill.RobloxLocked = true
Kill.Parent = TempSlot
local GearImage = Instance.new("ImageLabel")
GearImage.Name = "GearImage"
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0, 0, 0, 0)
GearImage.Size = UDim2.new(1, 0, 1, 0)
GearImage.ZIndex = 5.0
-- GearImage.RobloxLocked = true
GearImage.Parent = TempSlot
local SlotNumber = Instance.new("TextLabel")
SlotNumber.Name = "SlotNumber"
SlotNumber.BackgroundTransparency = 1
SlotNumber.BorderSizePixel = 0
SlotNumber.Font = Enum.Font.ArialBold
SlotNumber.FontSize = Enum.FontSize.Size18
SlotNumber.Position = UDim2.new(0, 0, 0, 0)
SlotNumber.Size = UDim2.new(0,10,0,15)
SlotNumber.TextColor3 = Color3.new(1,1,1)
SlotNumber.TextTransparency = 0
SlotNumber.TextXAlignment = Enum.TextXAlignment.Left
SlotNumber.TextYAlignment = Enum.TextYAlignment.Bottom
-- SlotNumber.RobloxLocked = true
SlotNumber.Parent = TempSlot
SlotNumber.ZIndex = 5
local SlotNumberDownShadow = SlotNumber:Clone()
SlotNumberDownShadow.Name = "SlotNumberDownShadow"
SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0)
SlotNumberDownShadow.Position = UDim2.new(0, 1, 0, -1)
SlotNumberDownShadow.Parent = TempSlot
SlotNumberDownShadow.ZIndex = 2
local SlotNumberUpShadow = SlotNumberDownShadow:Clone()
SlotNumberUpShadow.Name = "SlotNumberUpShadow"
SlotNumberUpShadow.Position = UDim2.new(0, -1, 0, -1)
SlotNumberUpShadow.Parent = TempSlot
local GearText = Instance.new("TextLabel")
-- GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,-8,0,-8)
GearText.Size = UDim2.new(1,16,1,16)
GearText.Text = ""
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = TempSlot
GearText.ZIndex = 5.0
--- Great, now lets make the inventory!
local Backpack = Instance.new("Frame")
--Backpack.RobloxLocked = true
Backpack.Visible = false
Backpack.Name = "Backpack"
Backpack.Position = UDim2.new(0.5, 0, 0.5, 0)
Backpack.BackgroundColor3 = Color3.new(32/255, 32/255, 32/255)
Backpack.BackgroundTransparency = 0.0
Backpack.BorderSizePixel = 0
Backpack.Parent = gui
Backpack.Active = true
-- Backpack Children
local SwapSlot = Instance.new("BoolValue")
-- SwapSlot.RobloxLocked = true
SwapSlot.Name = "SwapSlot"
SwapSlot.Parent = Backpack
-- SwapSlot Children
local Slot = Instance.new("IntValue")
-- Slot.RobloxLocked = true
Slot.Name = "Slot"
Slot.Parent = SwapSlot
local GearButton = Instance.new("ObjectValue")
-- GearButton.RobloxLocked = true
GearButton.Name = "GearButton"
GearButton.Parent = SwapSlot
--[[local Tabs = Instance.new("Frame")
Tabs.Name = "Tabs"
Tabs.Visible = false
Tabs.Active = false
-- Tabs.RobloxLocked = true
Tabs.BackgroundColor3 = Color3.new(0,0,0)
Tabs.BackgroundTransparency = 0.08
Tabs.BorderSizePixel = 0
Tabs.Position = UDim2.new(0,0,-0.1,-4)
Tabs.Size = UDim2.new(1,0,0.1,4)
Tabs.Parent = Backpack
-- Tabs Children
local tabLine = Instance.new("Frame")
-- tabLine.RobloxLocked = true
tabLine.Name = "TabLine"
tabLine.BackgroundColor3 = Color3.new(53/255, 53/255, 53/255)
tabLine.BorderSizePixel = 0
tabLine.Position = UDim2.new(0,5,1,-4)
tabLine.Size = UDim2.new(1,-10,0,4)
tabLine.ZIndex = 2
tabLine.Parent = Tabs
local InventoryButton = Instance.new("TextButton")
-- InventoryButton.RobloxLocked = true
InventoryButton.Name = "InventoryButton"
InventoryButton.Size = UDim2.new(0,60,0,30)
InventoryButton.Position = UDim2.new(0,7,1,-31)
InventoryButton.BackgroundColor3 = Color3.new(1,1,1)
InventoryButton.BorderColor3 = Color3.new(1,1,1)
InventoryButton.Font = Enum.Font.ArialBold
InventoryButton.FontSize = Enum.FontSize.Size18
InventoryButton.Text = "Gear"
InventoryButton.AutoButtonColor = false
InventoryButton.TextColor3 = Color3.new(0,0,0)
InventoryButton.Selected = true
InventoryButton.Active = true
InventoryButton.ZIndex = 3
InventoryButton.Parent = Tabs
local closeButton = Instance.new("TextButton")
-- closeButton.RobloxLocked = true
closeButton.Name = "CloseButton"
closeButton.Font = Enum.Font.ArialBold
closeButton.FontSize = Enum.FontSize.Size24
closeButton.Position = UDim2.new(1,-33,0,4)
closeButton.Size = UDim2.new(0,30,0,30)
closeButton.Style = Enum.ButtonStyle.RobloxButton
closeButton.Text = ""
closeButton.TextColor3 = Color3.new(1,1,1)
closeButton.Parent = Tabs
closeButton.Modal = true
--closeButton child
local XImage = Instance.new("ImageLabel")
-- XImage.RobloxLocked = true
XImage.Name = "XImage"
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75547445")
XImage.Image = "http://www.roblox.com/asset/?id=75547445" --TODO: move to rbxasset
XImage.BackgroundTransparency = 1
XImage.Position = UDim2.new(-.25,-1,-.25,-1)
XImage.Size = UDim2.new(1.5,2,1.5,2)
XImage.ZIndex = 2
XImage.Parent = closeButton--]]
-- Generic Search gui used across backpack
local SearchFrame = Instance.new("Frame")
-- SearchFrame.RobloxLocked = true
SearchFrame.Name = "SearchFrame"
SearchFrame.BackgroundTransparency = 1
SearchFrame.Position = UDim2.new(1,-220,0,2)
SearchFrame.Size = UDim2.new(0,220,0,24)
SearchFrame.Parent = Backpack
-- SearchFrame Children
local SearchButton = Instance.new("ImageButton")
-- SearchButton.RobloxLocked = true
SearchButton.Name = "SearchButton"
SearchButton.Size = UDim2.new(0,25,0,25)
SearchButton.BackgroundTransparency = 1
SearchButton.Image = "rbxasset://textures/ui/SearchIcon.png"
SearchButton.Parent = SearchFrame
local SearchBoxFrame = Instance.new("TextButton")
-- SearchBoxFrame.RobloxLocked = true
SearchBoxFrame.Position = UDim2.new(0,25,0,0)
SearchBoxFrame.Size = UDim2.new(1,-28,0,26)
SearchBoxFrame.Name = "SearchBoxFrame"
SearchBoxFrame.Text = ""
SearchBoxFrame.Style = Enum.ButtonStyle.RobloxButton
SearchBoxFrame.Parent = SearchFrame
-- SearchBoxFrame Children
local SearchBox = Instance.new("TextBox")
-- SearchBox.RobloxLocked = true
SearchBox.Name = "SearchBox"
SearchBox.BackgroundTransparency = 1
SearchBox.Font = Enum.Font.ArialBold
SearchBox.FontSize = Enum.FontSize.Size12
SearchBox.Position = UDim2.new(0,-5,0,-5)
SearchBox.Size = UDim2.new(1,10,1,10)
SearchBox.TextColor3 = Color3.new(1,1,1)
SearchBox.TextXAlignment = Enum.TextXAlignment.Left
SearchBox.ZIndex = 2
SearchBox.TextWrap = true
SearchBox.Text = "Search..."
SearchBox.Parent = SearchBoxFrame
local ResetButton = Instance.new("TextButton")
-- ResetButton.RobloxLocked = true
ResetButton.Visible = false
ResetButton.Name = "ResetButton"
ResetButton.Position = UDim2.new(1,-26,0,3)
ResetButton.Size = UDim2.new(0,20,0,20)
ResetButton.Style = Enum.ButtonStyle.RobloxButtonDefault
ResetButton.Text = "X"
ResetButton.TextColor3 = Color3.new(1,1,1)
ResetButton.Font = Enum.Font.ArialBold
ResetButton.FontSize = Enum.FontSize.Size18
ResetButton.ZIndex = 3
ResetButton.Parent = SearchFrame
------------------------------- GEAR -------------------------------------------------------
local Gear = Instance.new("Frame")
Gear.Name = "Gear"
-- Gear.RobloxLocked = true
Gear.BackgroundTransparency = 1
Gear.Size = UDim2.new(1,0,1,0)
Gear.Parent = Backpack
-- Gear Children
local AssetsList = Instance.new("Frame")
-- AssetsList.RobloxLocked = true
AssetsList.Name = "AssetsList"
AssetsList.BackgroundTransparency = 1
AssetsList.Size = UDim2.new(0.2,0,1,0)
AssetsList.Style = Enum.FrameStyle.RobloxSquare
AssetsList.Visible = false
AssetsList.Parent = Gear
local GearGrid = Instance.new("Frame")
-- GearGrid.RobloxLocked = true
GearGrid.Name = "GearGrid"
GearGrid.Size = UDim2.new(0.95, 0, 1, 0)
GearGrid.BackgroundTransparency = 1
GearGrid.Parent = Gear
local GearButton = Instance.new("ImageButton")
-- GearButton.RobloxLocked = true
GearButton.Visible = false
GearButton.Name = "GearButton"
GearButton.Size = UDim2.new(0, 54, 0, 54)
GearButton.Style = 'Custom'
GearButton.Parent = GearGrid
GearButton.BackgroundTransparency = 1.0
local slotBackground = Instance.new('ImageLabel')
slotBackground.Name = 'Background'
slotBackground.BackgroundTransparency = 1.0
slotBackground.Image = 'http://www.roblox.com/asset/?id=97613075'
slotBackground.Size = UDim2.new(1, 0, 1, 0)
slotBackground.Parent = GearButton
-- GearButton Children
local GearReference = Instance.new("ObjectValue")
-- GearReference.ed = true
GearReference.Name = "GearReference"
GearReference.Parent = GearButton
local GreyOutButton = Instance.new("Frame")
-- GreyOutButton.RobloxLocked = true
GreyOutButton.Name = "GreyOutButton"
GreyOutButton.BackgroundTransparency = 0.5
GreyOutButton.Size = UDim2.new(1,0,1,0)
GreyOutButton.Active = true
GreyOutButton.Visible = false
GreyOutButton.ZIndex = 3
GreyOutButton.Parent = GearButton
local GearText = Instance.new("TextLabel")
-- GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,-8,0,-8)
GearText.Size = UDim2.new(1,16,1,16)
GearText.Text = ""
GearText.ZIndex = 2
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = GearButton
local GearGridScrollingArea = Instance.new("Frame")
--GearGridScrollingArea.RobloxLocked = true
GearGridScrollingArea.Name = "GearGridScrollingArea"
GearGridScrollingArea.Position = UDim2.new(1, -19, 0, 35)
GearGridScrollingArea.Size = UDim2.new(0, 17, 1, -45)
GearGridScrollingArea.BackgroundTransparency = 1
GearGridScrollingArea.Parent = Gear
local GearLoadouts = Instance.new("Frame")
--GearLoadouts.RobloxLocked = true
GearLoadouts.Name = "GearLoadouts"
GearLoadouts.BackgroundTransparency = 1
GearLoadouts.Position = UDim2.new(0.7,23,0.5,1)
GearLoadouts.Size = UDim2.new(0.3,-23,0.5,-1)
GearLoadouts.Parent = Gear
GearLoadouts.Visible = false
-- GearLoadouts Children
local GearLoadoutsHeader = Instance.new("Frame")
--GearLoadoutsHeader.RobloxLocked = true
GearLoadoutsHeader.Name = "GearLoadoutsHeader"
GearLoadoutsHeader.BackgroundColor3 = Color3.new(0,0,0)
GearLoadoutsHeader.BackgroundTransparency = 0.2
GearLoadoutsHeader.BorderColor3 = Color3.new(1,0,0)
GearLoadoutsHeader.Size = UDim2.new(1,2,0.15,-1)
GearLoadoutsHeader.Parent = GearLoadouts
-- GearLoadoutsHeader Children
local LoadoutsHeaderText = Instance.new("TextLabel")
--LoadoutsHeaderText.RobloxLocked = true
LoadoutsHeaderText.Name = "LoadoutsHeaderText"
LoadoutsHeaderText.BackgroundTransparency = 1
LoadoutsHeaderText.Font = Enum.Font.ArialBold
LoadoutsHeaderText.FontSize = Enum.FontSize.Size18
LoadoutsHeaderText.Size = UDim2.new(1,0,1,0)
LoadoutsHeaderText.Text = "Loadouts"
LoadoutsHeaderText.TextColor3 = Color3.new(1,1,1)
LoadoutsHeaderText.Parent = GearLoadoutsHeader
local GearLoadoutsScrollingArea = GearGridScrollingArea:clone()
GearLoadoutsScrollingArea.Name = "GearLoadoutsScrollingArea"
GearLoadoutsScrollingArea.Position = UDim2.new(1,-15,0.15,2)
GearLoadoutsScrollingArea.Size = UDim2.new(0,17,0.85,-2)
GearLoadoutsScrollingArea.Parent = GearLoadouts
local LoadoutsList = Instance.new("Frame")
LoadoutsList.Name = "LoadoutsList"
LoadoutsList.Position = UDim2.new(0,0,0.15,2)
LoadoutsList.Size = UDim2.new(1,-17,0.85,-2)
LoadoutsList.Style = Enum.FrameStyle.RobloxSquare
LoadoutsList.Parent = GearLoadouts
local GearPreview = Instance.new("Frame")
GearPreview.Name = "GearPreview"
GearPreview.Position = UDim2.new(0.7,23,0,0)
GearPreview.Size = UDim2.new(0.3,-28,0.5,-1)
GearPreview.BackgroundTransparency = 1
GearPreview.ZIndex = 7
GearPreview.Parent = Gear
-- GearPreview Children
local GearStats = Instance.new("Frame")
GearStats.Name = "GearStats"
GearStats.BackgroundTransparency = 1
GearStats.Position = UDim2.new(0,0,0.75,0)
GearStats.Size = UDim2.new(1,0,0.25,0)
GearStats.ZIndex = 8
GearStats.Parent = GearPreview
-- GearStats Children
local GearName = Instance.new("TextLabel")
GearName.Name = "GearName"
GearName.BackgroundTransparency = 1
GearName.Font = Enum.Font.ArialBold
GearName.FontSize = Enum.FontSize.Size18
GearName.Position = UDim2.new(0,-3,0,0)
GearName.Size = UDim2.new(1,6,1,5)
GearName.Text = ""
GearName.TextColor3 = Color3.new(1,1,1)
GearName.TextWrap = true
GearName.ZIndex = 9
GearName.Parent = GearStats
local GearImage = Instance.new("ImageLabel")
GearImage.Name = "GearImage"
GearImage.Image = ""
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0.125,0,0,0)
GearImage.Size = UDim2.new(0.75,0,0.75,0)
GearImage.ZIndex = 8
GearImage.Parent = GearPreview
--GearImage Children
local GearIcons = Instance.new("Frame")
GearIcons.BackgroundColor3 = Color3.new(0,0,0)
GearIcons.BackgroundTransparency = 0.5
GearIcons.BorderSizePixel = 0
GearIcons.Name = "GearIcons"
GearIcons.Position = UDim2.new(0.4,2,0.85,-2)
GearIcons.Size = UDim2.new(0.6,0,0.15,0)
GearIcons.Visible = false
GearIcons.ZIndex = 9
GearIcons.Parent = GearImage
-- GearIcons Children
local GenreImage = Instance.new("ImageLabel")
GenreImage.Name = "GenreImage"
GenreImage.BackgroundColor3 = Color3.new(102/255,153/255,1)
GenreImage.BackgroundTransparency = 0.5
GenreImage.BorderSizePixel = 0
GenreImage.Size = UDim2.new(0.25,0,1,0)
GenreImage.Parent = GearIcons
local AttributeOneImage = GenreImage:clone()
AttributeOneImage.Name = "AttributeOneImage"
AttributeOneImage.BackgroundColor3 = Color3.new(1,51/255,0)
AttributeOneImage.Position = UDim2.new(0.25,0,0,0)
AttributeOneImage.Parent = GearIcons
local AttributeTwoImage = GenreImage:clone()
AttributeTwoImage.Name = "AttributeTwoImage"
AttributeTwoImage.BackgroundColor3 = Color3.new(153/255,1,153/255)
AttributeTwoImage.Position = UDim2.new(0.5,0,0,0)
AttributeTwoImage.Parent = GearIcons
local AttributeThreeImage = GenreImage:clone()
AttributeThreeImage.Name = "AttributeThreeImage"
AttributeThreeImage.BackgroundColor3 = Color3.new(0,0.5,0.5)
AttributeThreeImage.Position = UDim2.new(0.75,0,0,0)
AttributeThreeImage.Parent = GearIcons
-
false
BackpackGear
--rbxsig%IEUAo3Q1k4Rwb3ZcqPBum//j3+Jm/9Nv0JyCeCRWUrggWps7aG81/aPzlH9pPlMkkdsZwLsCRu6eTTrqzXn2DAJNPRs7y8akc3z91r1DP3jwomfpdT+2DBAmPk3Cdj8NXQzP6T+uEYm2kk2TW9pXonKvCgRVqXFx8J7mTr+aM1M=%
--rbxassetid%45284430%
local t = {}
local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
local eventConnection = nil
--Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
local tryConnect = function()
if game:IsAncestorOf(parentInstance) then
--Entering the world, make sure we are connected/synced
if not eventConnection then
eventConnection = instance[event]:connect(signalFunc)
if syncFunc then syncFunc() end
end
else
--Probably leaving the world, so disconnect for now
if eventConnection then
eventConnection:disconnect()
if removeFunc then removeFunc() end
end
end
end
--Hook it up to ancestryChanged signal
local connection = parentInstance.AncestryChanged:connect(tryConnect)
--Now connect us if we're already in the world
tryConnect()
return connection
end
local function getScreenGuiAncestor(instance)
local localInstance = instance
while localInstance and not localInstance:IsA("ScreenGui") do
localInstance = localInstance.Parent
end
return localInstance
end
local function CreateButtons(frame, buttons, yPos, ySize)
local buttonNum = 1
local buttonObjs = {}
for i, obj in ipairs(buttons) do
local button = Instance.new("TextButton")
button.Name = "Button" .. buttonNum
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size18
button.AutoButtonColor = true
button.Modal = true
if obj["Style"] then
button.Style = obj.Style
else
button.Style = Enum.ButtonStyle.RobloxButton
end
if obj["ZIndex"] then
button.ZIndex = obj.ZIndex
end
button.Text = obj.Text
button.TextColor3 = Color3.new(1,1,1)
button.MouseButton1Click:connect(obj.Function)
button.Parent = frame
buttonObjs[buttonNum] = button
buttonNum = buttonNum + 1
end
local numButtons = buttonNum-1
if numButtons == 1 then
frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
elseif numButtons == 2 then
frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
elseif numButtons >= 3 then
local spacing = .1 / numButtons
local buttonSize = .9 / numButtons
buttonNum = 1
while buttonNum <= numButtons do
buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
buttonNum = buttonNum + 1
end
end
end
local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
local newStep = steps - 1 --otherwise we really get one more step than we want
local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
local wholeNum, remainder = math.modf(relativePosX * newStep)
if remainder > 0.5 then
wholeNum = wholeNum + 1
end
relativePosX = wholeNum/newStep
local result = math.ceil(relativePosX * newStep)
if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
sliderPosition.Value = result + 1
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end
end
local function cancelSlide(areaSoak)
areaSoak.Visible = false
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
end
t.CreateStyledMessageDialog = function(title, message, style, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0, 165)
frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local styleImage = Instance.new("ImageLabel")
styleImage.Name = "StyleImage"
styleImage.BackgroundTransparency = 1
styleImage.Position = UDim2.new(0,5,0,15)
if style == "error" or style == "Error" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42565285"
elseif style == "notify" or style == "Notify" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42604978"
elseif style == "confirm" or style == "Confirm" then
styleImage.Size = UDim2.new(0, 74, 0, 76)
styleImage.Image = "http://www.roblox.com/asset/?id=42557901"
else
return t.CreateMessageDialog(title,message,buttons)
end
styleImage.Parent = frame
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.TextStrokeTransparency = 0
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 80, 0, 0)
titleLabel.Size = UDim2.new(1, -80, 0, 40)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextStrokeTransparency = 0
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
return frame
end
t.CreateMessageDialog = function(title, message, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0.5, 0)
frame.Position = UDim2.new(0.25, 0, 0.25, 0)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 0, 0, 0)
titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
return frame
end
t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ)
local baseZIndex = 0
if (type(baseZ) == "number") then
baseZIndex = baseZ
end
local width = UDim.new(0, 100)
local height = UDim.new(0, 32)
local xPos = 0.055
local frame = Instance.new("Frame")
local textColor = Color3.new(1,1,1)
if (whiteSkin) then
textColor = Color3.new(0.5, 0.5, 0.5)
end
frame.Name = "DropDownMenu"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(width, height)
local dropDownMenu = Instance.new("TextButton")
dropDownMenu.Name = "DropDownMenuButton"
dropDownMenu.TextWrap = true
dropDownMenu.TextColor3 = textColor
dropDownMenu.Text = "Choose One"
dropDownMenu.Font = Enum.Font.ArialBold
dropDownMenu.FontSize = Enum.FontSize.Size18
dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
dropDownMenu.BackgroundTransparency = 1
dropDownMenu.AutoButtonColor = true
if (whiteSkin) then
dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
dropDownMenu.Size = UDim2.new(1,0,1,0)
dropDownMenu.Parent = frame
dropDownMenu.ZIndex = 2 + baseZIndex
local dropDownIcon = Instance.new("ImageLabel")
dropDownIcon.Name = "Icon"
dropDownIcon.Active = false
if (whiteSkin) then
dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png"
dropDownIcon.Size = UDim2.new(0,16,0,12)
dropDownIcon.Position = UDim2.new(1,-17,0.5, -6)
else
dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894"
dropDownIcon.Size = UDim2.new(0,11,0,6)
dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
end
dropDownIcon.BackgroundTransparency = 1
dropDownIcon.Parent = dropDownMenu
dropDownIcon.ZIndex = 2 + baseZIndex
local itemCount = #items
local dropDownItemCount = #items
local useScrollButtons = false
if dropDownItemCount > 6 then
useScrollButtons = true
dropDownItemCount = 6
end
local droppedDownMenu = Instance.new("TextButton")
droppedDownMenu.Name = "List"
droppedDownMenu.Text = ""
droppedDownMenu.BackgroundTransparency = 1
--droppedDownMenu.AutoButtonColor = true
if (whiteSkin) then
droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
droppedDownMenu.Visible = false
droppedDownMenu.Active = true --Blocks clicks
droppedDownMenu.Position = UDim2.new(0,0,0,0)
droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
droppedDownMenu.Parent = frame
droppedDownMenu.ZIndex = 2 + baseZIndex
local choiceButton = Instance.new("TextButton")
choiceButton.Name = "ChoiceButton"
choiceButton.BackgroundTransparency = 1
choiceButton.BorderSizePixel = 0
choiceButton.Text = "ReplaceMe"
choiceButton.TextColor3 = textColor
choiceButton.TextXAlignment = Enum.TextXAlignment.Left
choiceButton.TextYAlignment = Enum.TextYAlignment.Center
choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
choiceButton.Font = Enum.Font.Arial
choiceButton.FontSize = Enum.FontSize.Size18
if useScrollButtons then
choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
else
choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
end
choiceButton.TextWrap = true
choiceButton.ZIndex = 2 + baseZIndex
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = true
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 3 + baseZIndex
local dropDownSelected = false
local scrollUpButton
local scrollDownButton
local scrollMouseCount = 0
local setZIndex = function(baseZIndex)
droppedDownMenu.ZIndex = baseZIndex +1
if scrollUpButton then
scrollUpButton.ZIndex = baseZIndex + 3
end
if scrollDownButton then
scrollDownButton.ZIndex = baseZIndex + 3
end
local children = droppedDownMenu:GetChildren()
if children then
for i, child in ipairs(children) do
if child.Name == "ChoiceButton" then
child.ZIndex = baseZIndex + 2
elseif child.Name == "ClickCaptureButton" then
child.ZIndex = baseZIndex
end
end
end
end
local scrollBarPosition = 1
local updateScroll = function()
if scrollUpButton then
scrollUpButton.Active = scrollBarPosition > 1
end
if scrollDownButton then
scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
end
local children = droppedDownMenu:GetChildren()
if not children then return end
local childNum = 1
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
obj.Visible = false
else
obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
obj.Visible = true
end
obj.TextColor3 = textColor
obj.BackgroundTransparency = 1
childNum = childNum + 1
end
end
end
local toggleVisibility = function()
dropDownSelected = not dropDownSelected
areaSoak.Visible = not areaSoak.Visible
dropDownMenu.Visible = not dropDownSelected
droppedDownMenu.Visible = dropDownSelected
if dropDownSelected then
setZIndex(4 + baseZIndex)
else
setZIndex(2 + baseZIndex)
end
if useScrollButtons then
updateScroll()
end
end
droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
local updateSelection = function(text)
local foundItem = false
local children = droppedDownMenu:GetChildren()
local childNum = 1
if children then
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if obj.Text == text then
obj.Font = Enum.Font.ArialBold
foundItem = true
scrollBarPosition = childNum
if (whiteSkin) then
obj.TextColor3 = Color3.new(90/255,142/255,233/255)
end
else
obj.Font = Enum.Font.Arial
if (whiteSkin) then
obj.TextColor3 = textColor
end
end
childNum = childNum + 1
end
end
end
if not text then
dropDownMenu.Text = "Choose One"
scrollBarPosition = 1
else
if not foundItem then
error("Invalid Selection Update -- " .. text)
end
if scrollBarPosition + dropDownItemCount > itemCount + 1 then
scrollBarPosition = itemCount - dropDownItemCount + 1
end
dropDownMenu.Text = text
end
end
local function scrollDown()
if scrollBarPosition + dropDownItemCount <= itemCount then
scrollBarPosition = scrollBarPosition + 1
updateScroll()
return true
end
return false
end
local function scrollUp()
if scrollBarPosition > 1 then
scrollBarPosition = scrollBarPosition - 1
updateScroll()
return true
end
return false
end
if useScrollButtons then
--Make some scroll buttons
scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
scrollUpButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollUp()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollUp() == false then
break
end
wait(0.1)
end
end)
scrollUpButton.Parent = droppedDownMenu
scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
scrollDownButton.Position = UDim2.new(1,-11,1,-11)
scrollDownButton.Parent = droppedDownMenu
scrollDownButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollDown()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollDown() == false then
break
end
wait(0.1)
end
end)
local scrollbar = Instance.new("ImageLabel")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
scrollbar.Parent = droppedDownMenu
end
for i,item in ipairs(items) do
-- needed to maintain local scope for items in event listeners below
local button = choiceButton:clone()
if forRoblox then
button.RobloxLocked = true
end
button.Text = item
button.Parent = droppedDownMenu
if (whiteSkin) then
button.TextColor3 = textColor
end
button.MouseButton1Click:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
updateSelection(item)
onSelect(item)
toggleVisibility()
end)
button.MouseEnter:connect(function()
--Add Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(0,0,0)
end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
end)
end
--This does the initial layout of the buttons
updateScroll()
frame.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(frame)
end
end)
dropDownMenu.MouseButton1Click:connect(toggleVisibility)
areaSoak.MouseButton1Click:connect(toggleVisibility)
return frame, updateSelection
end
t.CreatePropertyDropDownMenu = function(instance, property, enum)
local items = enum:GetEnumItems()
local names = {}
local nameToItem = {}
for i,obj in ipairs(items) do
names[i] = obj.Name
nameToItem[obj.Name] = obj
end
local frame
local updateSelection
frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
ScopedConnect(frame, instance, "Changed",
function(prop)
if prop == property then
updateSelection(instance[property].Name)
end
end,
function()
updateSelection(instance[property].Name)
end)
return frame
end
t.GetFontHeight = function(font, fontSize)
if font == nil or fontSize == nil then
error("Font and FontSize must be non-nil")
end
if font == Enum.Font.Legacy then
if fontSize == Enum.FontSize.Size8 then
return 12
elseif fontSize == Enum.FontSize.Size9 then
return 14
elseif fontSize == Enum.FontSize.Size10 then
return 15
elseif fontSize == Enum.FontSize.Size11 then
return 17
elseif fontSize == Enum.FontSize.Size12 then
return 18
elseif fontSize == Enum.FontSize.Size14 then
return 21
elseif fontSize == Enum.FontSize.Size18 then
return 27
elseif fontSize == Enum.FontSize.Size24 then
return 36
elseif fontSize == Enum.FontSize.Size36 then
return 54
elseif fontSize == Enum.FontSize.Size48 then
return 72
else
error("Unknown FontSize")
end
elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
if fontSize == Enum.FontSize.Size8 then
return 8
elseif fontSize == Enum.FontSize.Size9 then
return 9
elseif fontSize == Enum.FontSize.Size10 then
return 10
elseif fontSize == Enum.FontSize.Size11 then
return 11
elseif fontSize == Enum.FontSize.Size12 then
return 12
elseif fontSize == Enum.FontSize.Size14 then
return 14
elseif fontSize == Enum.FontSize.Size18 then
return 18
elseif fontSize == Enum.FontSize.Size24 then
return 24
elseif fontSize == Enum.FontSize.Size36 then
return 36
elseif fontSize == Enum.FontSize.Size48 then
return 48
else
error("Unknown FontSize")
end
else
error("Unknown Font " .. font)
end
end
local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
for i, child in ipairs(guiObjects) do
if child:IsA("TextLabel") or child:IsA("TextButton") then
local isLabel = child:IsA("TextLabel")
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
if child.TextFits and child.TextBounds.Y < pixelsRemaining then
child.Visible = true
if isLabel then
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
else
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
end
while not child.TextFits do
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
end
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
else
child.Visible = false
pixelsRemaining = -1
end
else
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
child.Visible = (pixelsRemaining >= 0)
end
end
end
t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
if not frame:IsA("GuiObject") then
error("Frame must be a GuiObject")
end
for i, child in ipairs(guiObjects) do
if not child:IsA("GuiObject") then
error("All elements that are layed out must be of type GuiObject")
end
end
if not settingsTable then
settingsTable = {}
end
if not settingsTable["TextLabelSizePadY"] then
settingsTable["TextLabelSizePadY"] = 0
end
if not settingsTable["TextLabelPositionPadY"] then
settingsTable["TextLabelPositionPadY"] = 0
end
if not settingsTable["TextButtonSizePadY"] then
settingsTable["TextButtonSizePadY"] = 12
end
if not settingsTable["TextButtonPositionPadY"] then
settingsTable["TextButtonPositionPadY"] = 2
end
--Wrapper frame takes care of styled objects
local wrapperFrame = Instance.new("Frame")
wrapperFrame.Name = "WrapperFrame"
wrapperFrame.BackgroundTransparency = 1
wrapperFrame.Size = UDim2.new(1,0,1,0)
wrapperFrame.Parent = frame
for i, child in ipairs(guiObjects) do
child.Parent = wrapperFrame
end
local recalculate = function()
wait()
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(recalculate)
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
t.CreateSlider = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 4
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local bar = Instance.new("TextButton")
bar.Text = ""
bar.AutoButtonColor = false
bar.Name = "Bar"
bar.BackgroundColor3 = Color3.new(0,0,0)
if type(width) == "number" then
bar.Size = UDim2.new(0,width,0,5)
else
bar.Size = UDim2.new(0,200,0,5)
end
bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
bar.ZIndex = 2
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/Slider.png"
slider.Position = UDim2.new(0,0,0.5,-10)
slider.Size = UDim2.new(0,20,0,20)
slider.ZIndex = 3
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateSliderNew = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 6
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local sliderBarImgHeight = 7
local sliderBarCapImgWidth = 4
local bar = Instance.new("ImageButton")
bar.BackgroundTransparency = 1
bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png"
bar.Name = "Bar"
local displayWidth = 200
if type(width) == "number" then
bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight)
displayWidth = width - (sliderBarCapImgWidth * 2)
else
bar.Size = UDim2.new(0,200,0,sliderBarImgHeight)
end
bar.ZIndex = 3
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local barLeft = bar:clone()
barLeft.Name = "BarLeft"
barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png"
barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight)
barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset)
barLeft.Parent = sliderGui
barLeft.ZIndex = 3
local barRight = barLeft:clone()
barRight.Name = "BarRight"
barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png"
barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset)
barRight.Parent = sliderGui
local fillLeft = barLeft:clone()
fillLeft.Name = "FillLeft"
fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png"
fillLeft.Parent = sliderGui
fillLeft.ZIndex = 4
local fill = fillLeft:clone()
fill.Name = "Fill"
fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png"
fill.Parent = bar
fill.ZIndex = 4
fill.Position = UDim2.new(0, 0, 0, 0)
fill.Size = UDim2.new(0.5, 0, 1, 0)
-- bar.Visible = false
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/slider_new_tab.png"
slider.Position = UDim2.new(0,0,0.5,-14)
slider.Size = UDim2.new(0,28,0,28)
slider.ZIndex = 5
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
fill.Size = UDim2.new(relativePosX, 0, 1, 0)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateTrueScrollingFrame = function()
local lowY = nil
local highY = nil
local dragCon = nil
local upCon = nil
local internalChange = false
local descendantsChangeConMap = {}
local scrollingFrame = Instance.new("Frame")
scrollingFrame.Name = "ScrollingFrame"
scrollingFrame.Active = true
scrollingFrame.Size = UDim2.new(1,0,1,0)
scrollingFrame.ClipsDescendants = true
local controlFrame = Instance.new("Frame")
controlFrame.Name = "ControlFrame"
controlFrame.BackgroundTransparency = 1
controlFrame.Size = UDim2.new(0,18,1,0)
controlFrame.Position = UDim2.new(1,-20,0,0)
controlFrame.Parent = scrollingFrame
local scrollBottom = Instance.new("BoolValue")
scrollBottom.Value = false
scrollBottom.Name = "ScrollBottom"
scrollBottom.Parent = controlFrame
local scrollUp = Instance.new("BoolValue")
scrollUp.Value = false
scrollUp.Name = "scrollUp"
scrollUp.Parent = controlFrame
local scrollUpButton = Instance.new("TextButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.Text = ""
scrollUpButton.AutoButtonColor = false
scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
scrollUpButton.BorderColor3 = Color3.new(1,1,1)
scrollUpButton.BackgroundTransparency = 0.5
scrollUpButton.Size = UDim2.new(0,18,0,18)
scrollUpButton.ZIndex = 2
scrollUpButton.Parent = controlFrame
for i = 1, 6 do
local triFrame = Instance.new("Frame")
triFrame.BorderColor3 = Color3.new(1,1,1)
triFrame.Name = "tri" .. tostring(i)
triFrame.ZIndex = 3
triFrame.BackgroundTransparency = 0.5
triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
triFrame.Parent = scrollUpButton
end
scrollUpButton.MouseEnter:connect(function()
scrollUpButton.BackgroundTransparency = 0.1
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.1
end
end)
scrollUpButton.MouseLeave:connect(function()
scrollUpButton.BackgroundTransparency = 0.5
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.5
end
end)
local scrollDownButton = scrollUpButton:clone()
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.Position = UDim2.new(0,0,1,-18)
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
end
scrollDownButton.MouseEnter:connect(function()
scrollDownButton.BackgroundTransparency = 0.1
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.1
end
end)
scrollDownButton.MouseLeave:connect(function()
scrollDownButton.BackgroundTransparency = 0.5
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.5
end
end)
scrollDownButton.Parent = controlFrame
local scrollTrack = Instance.new("Frame")
scrollTrack.Name = "ScrollTrack"
scrollTrack.BackgroundTransparency = 1
scrollTrack.Size = UDim2.new(0,18,1,-38)
scrollTrack.Position = UDim2.new(0,0,0,19)
scrollTrack.Parent = controlFrame
local scrollbar = Instance.new("TextButton")
scrollbar.BackgroundColor3 = Color3.new(0,0,0)
scrollbar.BorderColor3 = Color3.new(1,1,1)
scrollbar.BackgroundTransparency = 0.5
scrollbar.AutoButtonColor = false
scrollbar.Text = ""
scrollbar.Active = true
scrollbar.Name = "ScrollBar"
scrollbar.ZIndex = 2
scrollbar.BackgroundTransparency = 0.5
scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
scrollbar.Position = UDim2.new(0,0,0,0)
scrollbar.Parent = scrollTrack
local scrollNub = Instance.new("Frame")
scrollNub.Name = "ScrollNub"
scrollNub.BorderColor3 = Color3.new(1,1,1)
scrollNub.Size = UDim2.new(0,10,0,0)
scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
scrollNub.ZIndex = 2
scrollNub.BackgroundTransparency = 0.5
scrollNub.Parent = scrollbar
local newNub = scrollNub:clone()
newNub.Position = UDim2.new(0.5,-5,0.5,-2)
newNub.Parent = scrollbar
local lastNub = scrollNub:clone()
lastNub.Position = UDim2.new(0.5,-5,0.5,2)
lastNub.Parent = scrollbar
scrollbar.MouseEnter:connect(function()
scrollbar.BackgroundTransparency = 0.1
scrollNub.BackgroundTransparency = 0.1
newNub.BackgroundTransparency = 0.1
lastNub.BackgroundTransparency = 0.1
end)
scrollbar.MouseLeave:connect(function()
scrollbar.BackgroundTransparency = 0.5
scrollNub.BackgroundTransparency = 0.5
newNub.BackgroundTransparency = 0.5
lastNub.BackgroundTransparency = 0.5
end)
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local function positionScrollBar(x,y,offset)
local oldPos = scrollbar.Position
if y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
return (oldPos ~= scrollbar.Position)
end
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
return (oldPos ~= scrollbar.Position)
end
local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
if newScaleYPos + relativeSize > 1 then
newScaleYPos = 1 - relativeSize
scrollBottom.Value = true
scrollUp.Value = false
elseif newScaleYPos <= 0 then
newScaleYPos = 0
scrollUp.Value = true
scrollBottom.Value = false
else
scrollUp.Value = false
scrollBottom.Value = false
end
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
return (oldPos ~= scrollbar.Position)
end
local function drillDownSetHighLow(instance)
if not instance or not instance:IsA("GuiObject") then return end
if instance == controlFrame then return end
if instance:IsDescendantOf(controlFrame) then return end
if not instance.Visible then return end
if lowY and lowY > instance.AbsolutePosition.Y then
lowY = instance.AbsolutePosition.Y
elseif not lowY then
lowY = instance.AbsolutePosition.Y
end
if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
local children = instance:GetChildren()
for i = 1, #children do
drillDownSetHighLow(children[i])
end
end
local function resetHighLow()
local firstChildren = scrollingFrame:GetChildren()
for i = 1, #firstChildren do
drillDownSetHighLow(firstChildren[i])
end
end
local function recalculate()
internalChange = true
local percentFrame = 0
if scrollbar.Position.Y.Scale > 0 then
if scrollbar.Visible then
percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
else
percentFrame = 0
end
end
if percentFrame > 0.99 then percentFrame = 1 end
local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
local guiChildren = scrollingFrame:GetChildren()
for i = 1, #guiChildren do
if guiChildren[i] ~= controlFrame then
guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
end
end
lowY = nil
highY = nil
resetHighLow()
internalChange = false
end
local function setSliderSizeAndPosition()
if not highY or not lowY then return end
local totalYSpan = math.abs(highY - lowY)
if totalYSpan == 0 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
return
end
local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
if percentShown >= 1 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
recalculate()
else
scrollbar.Visible = true
scrollDownButton.Visible = true
scrollUpButton.Visible = true
scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
end
local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
end
if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
end
end
local buttonScrollAmountPixels = 7
local reentrancyGuardScrollUp = false
local function doScrollUp()
if reentrancyGuardScrollUp then return end
reentrancyGuardScrollUp = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollUp = false
end
local reentrancyGuardScrollDown = false
local function doScrollDown()
if reentrancyGuardScrollDown then return end
reentrancyGuardScrollDown = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollDown = false
end
local function scrollUp(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local function scrollDown(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
scrollbar.MouseButton1Down:connect(function(x,y)
if scrollbar.Active then
scrollStamp = tick()
local mouseOffset = y - scrollbar.AbsolutePosition.y
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
local prevY = y
local reentrancyGuardMouseScroll = false
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
if reentrancyGuardMouseScroll then return end
reentrancyGuardMouseScroll = true
if positionScrollBar(x,y,mouseOffset) then
recalculate()
end
reentrancyGuardMouseScroll = false
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
local function heightCheck(instance)
if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
setSliderSizeAndPosition()
end
local function highLowRecheck()
local oldLowY = lowY
local oldHighY = highY
lowY = nil
highY = nil
resetHighLow()
if (lowY ~= oldLowY) or (highY ~= oldHighY) then
setSliderSizeAndPosition()
end
end
local function descendantChanged(this, prop)
if internalChange then return end
if not this.Visible then return end
if prop == "Size" or prop == "Position" then
wait()
highLowRecheck()
end
end
scrollingFrame.DescendantAdded:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if instance.Visible then
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end
descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
end)
scrollingFrame.DescendantRemoving:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if descendantsChangeConMap[instance] then
descendantsChangeConMap[instance]:disconnect()
descendantsChangeConMap[instance] = nil
end
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end)
scrollingFrame.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if not highY or not lowY then return end
highLowRecheck()
setSliderSizeAndPosition()
end
end)
return scrollingFrame, controlFrame
end
t.CreateScrollingFrame = function(orderList,scrollStyle)
local frame = Instance.new("Frame")
frame.Name = "ScrollingFrame"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1,0,1,0)
local scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
local scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
local scrollbar = Instance.new("ImageButton")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, 0, 150)
local scrollStamp = 0
local scrollDrag = Instance.new("ImageButton")
scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186"
scrollDrag.Size = UDim2.new(1, 0, 0, 16)
scrollDrag.BackgroundTransparency = 1
scrollDrag.Name = "ScrollDrag"
scrollDrag.Active = true
scrollDrag.Parent = scrollbar
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local style = "simple"
if scrollStyle and tostring(scrollStyle) then
style = scrollStyle
end
local scrollPosition = 1
local rowSize = 0
local howManyDisplayed = 0
local layoutGridScrollBar = function()
howManyDisplayed = 0
local guiObjects = {}
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
if scrollPosition < 1 then scrollPosition = 1 end
local totalPixelsY = frame.AbsoluteSize.Y
local pixelsRemainingY = frame.AbsoluteSize.Y
local totalPixelsX = frame.AbsoluteSize.X
local xCounter = 0
local rowSizeCounter = 0
local setRowSize = true
local pixelsBelowScrollbar = 0
local pos = #guiObjects
local currentRowY = 0
pos = scrollPosition
--count up from current scroll position to fill out grid
while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
--previous pos was the end of a row
if xCounter >= totalPixelsX then
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
xCounter = guiObjects[pos].AbsoluteSize.X
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos + 1
end
--Count wherever current row left off
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
pos = scrollPosition - 1
xCounter = 0
--objects with varying X,Y dimensions can rarely cause minor errors
--rechecking every new scrollPosition is necessary to avoid 100% of errors
--count backwards from current scrollPosition to see if we can add more rows
while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
rowSizeCounter = rowSizeCounter + 1
if xCounter >= totalPixelsX then
rowSize = rowSizeCounter - 1
rowSizeCounter = 0
xCounter = guiObjects[pos].AbsoluteSize.X
if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
if scrollPosition <= rowSize then
scrollPosition = 1
break
else
scrollPosition = scrollPosition - rowSize
end
currentRowY = 0
else
break
end
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos - 1
end
--Do check last time if pos = 0
if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
scrollPosition = 1
end
xCounter = 0
--pos = scrollPosition
rowSizeCounter = 0
setRowSize = true
local lastChildSize = 0
local xOffset,yOffset = 0
if guiObjects[1] then
yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
end
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemainingY < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
if xCounter + child.AbsoluteSize.X >= totalPixelsX then
if setRowSize then
rowSize = rowSizeCounter - 1
setRowSize = false
end
xCounter = 0
pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
end
child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
xCounter = xCounter + child.AbsoluteSize.X
child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
if child.Visible then
howManyDisplayed = howManyDisplayed + 1
end
lastChildSize = child.AbsoluteSize
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
if lastChildSize == 0 then
scrollDownButton.Active = false
else
scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
end
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local layoutSimpleScrollBar = function()
local guiObjects = {}
howManyDisplayed = 0
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
local pixelsBelowScrollbar = 0
local pos = #guiObjects
while pixelsBelowScrollbar < totalPixels and pos >= 1 do
if pos >= scrollPosition then
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
else
if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
if scrollPosition <= 1 then
scrollPosition = 1
break
else
--local ("Backing up ScrollPosition from -- " ..scrollPosition)
scrollPosition = scrollPosition - 1
end
else
break
end
end
pos = pos - 1
end
pos = scrollPosition
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemaining < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if (pixelsRemaining >= 0) then
child.Visible = true
howManyDisplayed = howManyDisplayed + 1
else
child.Visible = false
end
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
scrollDownButton.Active = (pixelsRemaining < 0)
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local moveDragger = function()
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
if not scrollDrag.Parent then return end
local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
if dragSizeY < 16 then dragSizeY = 16 end
scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
if relativeYPos > 1 then relativeYPos = 1
elseif relativeYPos < 0 then relativeYPos = 0 end
local absYPos = 0
if relativeYPos ~= 0 then
absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
end
scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
end
local reentrancyGuard = false
local recalculate = function()
if reentrancyGuard then
return
end
reentrancyGuard = true
wait()
local success, err = nil
if style == "grid" then
success, err = pcall(function() layoutGridScrollBar() end)
elseif style == "simple" then
success, err = pcall(function() layoutSimpleScrollBar() end)
end
if not success then print(err) end
moveDragger()
reentrancyGuard = false
end
local doScrollUp = function()
scrollPosition = (scrollPosition) - rowSize
if scrollPosition < 1 then scrollPosition = 1 end
recalculate(nil)
end
local doScrollDown = function()
scrollPosition = (scrollPosition) + rowSize
recalculate(nil)
end
local scrollUp = function(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local scrollDown = function(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local y = 0
scrollDrag.MouseButton1Down:connect(function(x,y)
if scrollDrag.Active then
scrollStamp = tick()
local mouseOffset = y - scrollDrag.AbsolutePosition.y
local dragCon
local upCon
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
local barAbsPos = scrollbar.AbsolutePosition.y
local barAbsSize = scrollbar.AbsoluteSize.y
local dragAbsSize = scrollDrag.AbsoluteSize.y
local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
y = y - mouseOffset
y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
y = y - barAbsPos
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
local doublePercent = y/(barAbsSize-dragAbsSize)
local rowDiff = rowSize
local totalScrollCount = guiObjects - (howManyDisplayed - 1)
local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
if newScrollPosition < scrollPosition then
rowDiff = -rowDiff
end
if newScrollPosition < 1 then
newScrollPosition = 1
end
scrollPosition = newScrollPosition
recalculate(nil)
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(
function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollbar.MouseButton1Down:connect(
function(x,y)
if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
scrollDown(y)
elseif y < (scrollDrag.AbsolutePosition.y) then
scrollUp(y)
end
end)
frame.ChildAdded:connect(function()
recalculate(nil)
end)
frame.ChildRemoved:connect(function()
recalculate(nil)
end)
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(function() recalculate(nil) end)
return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
end
local function binaryGrow(min, max, fits)
if min > max then
return min
end
local biggestLegal = min
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
biggestLegal = mid
--Try growing
min = mid + 1
else
--Doesn't fit, shrink
max = mid - 1
end
end
return biggestLegal
end
local function binaryShrink(min, max, fits)
if min > max then
return min
end
local smallestLegal = max
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
smallestLegal = mid
--It fits, shrink
max = mid - 1
else
--Doesn't fit, grow
min = mid + 1
end
end
return smallestLegal
end
local function getGuiOwner(instance)
while instance ~= nil do
if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
return instance
end
instance = instance.Parent
end
return nil
end
t.AutoTruncateTextObject = function(textLabel)
local text = textLabel.Text
local fullLabel = textLabel:Clone()
fullLabel.Name = "Full" .. textLabel.Name
fullLabel.BorderSizePixel = 0
fullLabel.BackgroundTransparency = 0
fullLabel.Text = text
fullLabel.TextXAlignment = Enum.TextXAlignment.Center
fullLabel.Position = UDim2.new(0,-3,0,0)
fullLabel.Size = UDim2.new(0,100,1,0)
fullLabel.Visible = false
fullLabel.Parent = textLabel
local shortText = nil
local mouseEnterConnection = nil
local mouseLeaveConnection= nil
local checkForResize = function()
if getGuiOwner(textLabel) == nil then
return
end
textLabel.Text = text
if textLabel.TextFits then
--Tear down the rollover if it is active
if mouseEnterConnection then
mouseEnterConnection:disconnect()
mouseEnterConnection = nil
end
if mouseLeaveConnection then
mouseLeaveConnection:disconnect()
mouseLeaveConnection = nil
end
else
local len = string.len(text)
textLabel.Text = text .. "~"
--Shrink the text
local textSize = binaryGrow(0, len,
function(pos)
if pos == 0 then
textLabel.Text = "~"
else
textLabel.Text = string.sub(text, 1, pos) .. "~"
end
return textLabel.TextFits
end)
shortText = string.sub(text, 1, textSize) .. "~"
textLabel.Text = shortText
--Make sure the fullLabel fits
if not fullLabel.TextFits then
--Already too small, grow it really bit to start
fullLabel.Size = UDim2.new(0, 10000, 1, 0)
end
--Okay, now try to binary shrink it back down
local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
function(size)
fullLabel.Size = UDim2.new(0, size, 1, 0)
return fullLabel.TextFits
end)
fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
--Now setup the rollover effects, if they are currently off
if mouseEnterConnection == nil then
mouseEnterConnection = textLabel.MouseEnter:connect(
function()
fullLabel.ZIndex = textLabel.ZIndex + 1
fullLabel.Visible = true
--textLabel.Text = ""
end)
end
if mouseLeaveConnection == nil then
mouseLeaveConnection = textLabel.MouseLeave:connect(
function()
fullLabel.Visible = false
--textLabel.Text = shortText
end)
end
end
end
textLabel.AncestryChanged:connect(checkForResize)
textLabel.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
checkForResize()
end
end)
checkForResize()
local function changeText(newText)
text = newText
fullLabel.Text = text
checkForResize()
end
return textLabel, changeText
end
local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
if fromPage then
fromPage.Visible = false
if transitionFrame.Visible == false then
transitionFrame.Size = fromPage.Size
transitionFrame.Position = fromPage.Position
end
else
if transitionFrame.Visible == false then
transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
end
end
transitionFrame.Visible = true
currentPageValue.Value = nil
local newsize, newPosition
if toPage then
--Make it visible so it resizes
toPage.Visible = true
newSize = toPage.Size
newPosition = toPage.Position
toPage.Visible = false
else
newSize = UDim2.new(0.0,50,0.0,50)
newPosition = UDim2.new(0.5,-25,0.5,-25)
end
transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
function(state)
if state == Enum.TweenStatus.Completed then
transitionFrame.Visible = false
if toPage then
toPage.Visible = true
currentPageValue.Value = toPage
end
end
end)
end
t.CreateTutorial = function(name, tutorialKey, createButtons)
local frame = Instance.new("Frame")
frame.Name = "Tutorial-" .. name
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
local transitionFrame = Instance.new("Frame")
transitionFrame.Name = "TransitionFrame"
transitionFrame.Style = Enum.FrameStyle.RobloxRound
transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
transitionFrame.Visible = false
transitionFrame.Parent = frame
local currentPageValue = Instance.new("ObjectValue")
currentPageValue.Name = "CurrentTutorialPage"
currentPageValue.Value = nil
currentPageValue.Parent = frame
local boolValue = Instance.new("BoolValue")
boolValue.Name = "Buttons"
boolValue.Value = createButtons
boolValue.Parent = frame
local pages = Instance.new("Frame")
pages.Name = "Pages"
pages.BackgroundTransparency = 1
pages.Size = UDim2.new(1,0,1,0)
pages.Parent = frame
local function getVisiblePageAndHideOthers()
local visiblePage = nil
local children = pages:GetChildren()
if children then
for i,child in ipairs(children) do
if child.Visible then
if visiblePage then
child.Visible = false
else
visiblePage = child
end
end
end
end
return visiblePage
end
local showTutorial = function(alwaysShow)
if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
print("Showing tutorial-",tutorialKey)
local currentTutorialPage = getVisiblePageAndHideOthers()
local firstPage = pages:FindFirstChild("TutorialPage1")
if firstPage then
TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
else
error("Could not find TutorialPage1")
end
end
end
local dismissTutorial = function()
local currentTutorialPage = getVisiblePageAndHideOthers()
if currentTutorialPage then
TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
end
UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
end
local gotoPage = function(pageNum)
local page = pages:FindFirstChild("TutorialPage" .. pageNum)
local currentTutorialPage = getVisiblePageAndHideOthers()
TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
end
return frame, showTutorial, dismissTutorial, gotoPage
end
local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
local frame = Instance.new("Frame")
frame.Name = "TutorialPage"
frame.Style = Enum.FrameStyle.RobloxRound
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
frame.Visible = false
local frameHeader = Instance.new("TextLabel")
frameHeader.Name = "Header"
frameHeader.Text = name
frameHeader.BackgroundTransparency = 1
frameHeader.FontSize = Enum.FontSize.Size24
frameHeader.Font = Enum.Font.ArialBold
frameHeader.TextColor3 = Color3.new(1,1,1)
frameHeader.TextXAlignment = Enum.TextXAlignment.Center
frameHeader.TextWrap = true
frameHeader.Size = UDim2.new(1,-55, 0, 22)
frameHeader.Position = UDim2.new(0,0,0,0)
frameHeader.Parent = frame
local skipButton = Instance.new("ImageButton")
skipButton.Name = "SkipButton"
skipButton.AutoButtonColor = false
skipButton.BackgroundTransparency = 1
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
skipButton.MouseButton1Click:connect(function()
skipTutorial()
end)
skipButton.MouseEnter:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
end)
skipButton.MouseLeave:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
end)
skipButton.Size = UDim2.new(0, 25, 0, 25)
skipButton.Position = UDim2.new(1, -25, 0, 0)
skipButton.Parent = frame
if giveDoneButton then
local doneButton = Instance.new("TextButton")
doneButton.Name = "DoneButton"
doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
doneButton.Text = "Done"
doneButton.TextColor3 = Color3.new(1,1,1)
doneButton.Font = Enum.Font.ArialBold
doneButton.FontSize = Enum.FontSize.Size18
doneButton.Size = UDim2.new(0,100,0,50)
doneButton.Position = UDim2.new(0.5,-50,1,-50)
if skipTutorial then
doneButton.MouseButton1Click:connect(function() skipTutorial() end)
end
doneButton.Parent = frame
end
local innerFrame = Instance.new("Frame")
innerFrame.Name = "ContentFrame"
innerFrame.BackgroundTransparency = 1
innerFrame.Position = UDim2.new(0,0,0,25)
innerFrame.Parent = frame
local nextButton = Instance.new("TextButton")
nextButton.Name = "NextButton"
nextButton.Text = "Next"
nextButton.TextColor3 = Color3.new(1,1,1)
nextButton.Font = Enum.Font.Arial
nextButton.FontSize = Enum.FontSize.Size18
nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
nextButton.Size = UDim2.new(0,80, 0, 32)
nextButton.Position = UDim2.new(0.5, 5, 1, -32)
nextButton.Active = false
nextButton.Visible = false
nextButton.Parent = frame
local prevButton = Instance.new("TextButton")
prevButton.Name = "PrevButton"
prevButton.Text = "Previous"
prevButton.TextColor3 = Color3.new(1,1,1)
prevButton.Font = Enum.Font.Arial
prevButton.FontSize = Enum.FontSize.Size18
prevButton.Style = Enum.ButtonStyle.RobloxButton
prevButton.Size = UDim2.new(0,80, 0, 32)
prevButton.Position = UDim2.new(0.5, -85, 1, -32)
prevButton.Active = false
prevButton.Visible = false
prevButton.Parent = frame
if giveDoneButton then
innerFrame.Size = UDim2.new(1,0,1,-75)
else
innerFrame.Size = UDim2.new(1,0,1,-22)
end
local parentConnection = nil
local function basicHandleResize()
if frame.Visible and frame.Parent then
local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
handleResize(200,maxSize)
end
end
frame.Changed:connect(
function(prop)
if prop == "Parent" then
if parentConnection ~= nil then
parentConnection:disconnect()
parentConnection = nil
end
if frame.Parent and frame.Parent:IsA("GuiObject") then
parentConnection = frame.Parent.Changed:connect(
function(parentProp)
if parentProp == "AbsoluteSize" then
wait()
basicHandleResize()
end
end)
basicHandleResize()
end
end
if prop == "Visible" then
basicHandleResize()
end
end)
return frame, innerFrame
end
t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
local frame = nil
local contentFrame = nil
local textLabel = Instance.new("TextLabel")
textLabel.BackgroundTransparency = 1
textLabel.TextColor3 = Color3.new(1,1,1)
textLabel.Text = text
textLabel.TextWrap = true
textLabel.TextXAlignment = Enum.TextXAlignment.Left
textLabel.TextYAlignment = Enum.TextYAlignment.Center
textLabel.Font = Enum.Font.Arial
textLabel.FontSize = Enum.FontSize.Size14
textLabel.Size = UDim2.new(1,0,1,0)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
frame.Size = UDim2.new(0, size, 0, size)
return textLabel.TextFits
end)
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
textLabel.Parent = contentFrame
return frame
end
t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
local frame = nil
local contentFrame = nil
local imageLabel = Instance.new("ImageLabel")
imageLabel.BackgroundTransparency = 1
imageLabel.Image = imageAsset
imageLabel.Size = UDim2.new(0,x,0,y)
imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
return size >= x and size >= y
end)
if size >= x and size >= y then
imageLabel.Size = UDim2.new(0,x, 0,y)
imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
else
if x > y then
--X is limiter, so
imageLabel.Size = UDim2.new(1,0,y/x,0)
imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
else
--Y is limiter
imageLabel.Size = UDim2.new(x/y,0,1, 0)
imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
end
end
size = size + 50
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
imageLabel.Parent = contentFrame
return frame
end
t.AddTutorialPage = function(tutorial, tutorialPage)
local transitionFrame = tutorial.TransitionFrame
local currentPageValue = tutorial.CurrentTutorialPage
if not tutorial.Buttons.Value then
tutorialPage.NextButton.Parent = nil
tutorialPage.PrevButton.Parent = nil
end
local children = tutorial.Pages:GetChildren()
if children and #children > 0 then
tutorialPage.Name = "TutorialPage" .. (#children+1)
local previousPage = children[#children]
if not previousPage:IsA("GuiObject") then
error("All elements under Pages must be GuiObjects")
end
if tutorial.Buttons.Value then
if previousPage.NextButton.Active then
error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
end
previousPage.NextButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
end)
previousPage.NextButton.Active = true
previousPage.NextButton.Visible = true
if tutorialPage.PrevButton.Active then
error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
end
tutorialPage.PrevButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
end)
tutorialPage.PrevButton.Active = true
tutorialPage.PrevButton.Visible = true
end
tutorialPage.Parent = tutorial.Pages
else
--First child
tutorialPage.Name = "TutorialPage1"
tutorialPage.Parent = tutorial.Pages
end
end
t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
if not userIdsForSets then
error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
end
if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
end
if not objectSelected then
error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
end
if type(objectSelected) ~= "function" then
error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
end
if dialogClosed and type(dialogClosed) ~= "function" then
error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
end
if showAdminCategories == nil then -- by default, don't show beta sets
showAdminCategories = false
end
local arrayPosition = 1
local insertButtons = {}
local insertButtonCons = {}
local contents = nil
local setGui = nil
-- used for water selections
local waterForceDirection = "NegX"
local waterForce = "None"
local waterGui, waterTypeChangedEvent = nil
local Data = {}
Data.CurrentCategory = nil
Data.Category = {}
local SetCache = {}
local userCategoryButtons = nil
local buttonWidth = 64
local buttonHeight = buttonWidth
local SmallThumbnailUrl = nil
local LargeThumbnailUrl = nil
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if useAssetVersionId then
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
else
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
end
local function drillDownSetZIndex(parent, index)
local children = parent:GetChildren()
for i = 1, #children do
if children[i]:IsA("GuiObject") then
children[i].ZIndex = index
end
drillDownSetZIndex(children[i], index)
end
end
-- for terrain stamping
local currTerrainDropDownFrame = nil
local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
local terrainShapeMap = {}
for i = 1, #terrainShapes do
terrainShapeMap[terrainShapes[i]] = i - 1
end
terrainShapeMap[terrainShapes[#terrainShapes]] = 6
local function createWaterGui()
local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
local waterFrame = Instance.new("Frame")
waterFrame.Name = "WaterFrame"
waterFrame.Style = Enum.FrameStyle.RobloxSquare
waterFrame.Size = UDim2.new(0,150,0,110)
waterFrame.Visible = false
local waterForceLabel = Instance.new("TextLabel")
waterForceLabel.Name = "WaterForceLabel"
waterForceLabel.BackgroundTransparency = 1
waterForceLabel.Size = UDim2.new(1,0,0,12)
waterForceLabel.Font = Enum.Font.ArialBold
waterForceLabel.FontSize = Enum.FontSize.Size12
waterForceLabel.TextColor3 = Color3.new(1,1,1)
waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
waterForceLabel.Text = "Water Force"
waterForceLabel.Parent = waterFrame
local waterForceDirLabel = waterForceLabel:Clone()
waterForceDirLabel.Name = "WaterForceDirectionLabel"
waterForceDirLabel.Text = "Water Force Direction"
waterForceDirLabel.Position = UDim2.new(0,0,0,50)
waterForceDirLabel.Parent = waterFrame
local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
local waterForceDirectionSelectedFunc = function(newForceDirection)
waterForceDirection = newForceDirection
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceSelectedFunc = function(newForce)
waterForce = newForce
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
forceWaterDirectionSelection("NegX")
waterForceDirectionDropDown.Parent = waterForceDirLabel
local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
forceWaterForceSelection("None")
waterForceDropDown.Size = UDim2.new(1,0,0,25)
waterForceDropDown.Position = UDim2.new(0,0,1,3)
waterForceDropDown.Parent = waterForceLabel
return waterFrame, waterTypeChangedEvent
end
-- Helper Function that contructs gui elements
local function createSetGui()
local setGui = Instance.new("ScreenGui")
setGui.Name = "SetGui"
local setPanel = Instance.new("Frame")
setPanel.Name = "SetPanel"
setPanel.Active = true
setPanel.BackgroundTransparency = 1
if position then
setPanel.Position = position
else
setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
end
if size then
setPanel.Size = size
else
setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
end
setPanel.Style = Enum.FrameStyle.RobloxRound
setPanel.ZIndex = 6
setPanel.Parent = setGui
-- Children of SetPanel
local itemPreview = Instance.new("Frame")
itemPreview.Name = "ItemPreview"
itemPreview.BackgroundTransparency = 1
itemPreview.Position = UDim2.new(0.8,5,0.085,0)
itemPreview.Size = UDim2.new(0.21,0,0.9,0)
itemPreview.ZIndex = 6
itemPreview.Parent = setPanel
-- Children of ItemPreview
local textPanel = Instance.new("Frame")
textPanel.Name = "TextPanel"
textPanel.BackgroundTransparency = 1
textPanel.Position = UDim2.new(0,0,0.45,0)
textPanel.Size = UDim2.new(1,0,0.55,0)
textPanel.ZIndex = 6
textPanel.Parent = itemPreview
-- Children of TextPanel
local rolloverText = Instance.new("TextLabel")
rolloverText.Name = "RolloverText"
rolloverText.BackgroundTransparency = 1
rolloverText.Size = UDim2.new(1,0,0,48)
rolloverText.ZIndex = 6
rolloverText.Font = Enum.Font.ArialBold
rolloverText.FontSize = Enum.FontSize.Size24
rolloverText.Text = ""
rolloverText.TextColor3 = Color3.new(1,1,1)
rolloverText.TextWrap = true
rolloverText.TextXAlignment = Enum.TextXAlignment.Left
rolloverText.TextYAlignment = Enum.TextYAlignment.Top
rolloverText.Parent = textPanel
local largePreview = Instance.new("ImageLabel")
largePreview.Name = "LargePreview"
largePreview.BackgroundTransparency = 1
largePreview.Image = ""
largePreview.Size = UDim2.new(1,0,0,170)
largePreview.ZIndex = 6
largePreview.Parent = itemPreview
local sets = Instance.new("Frame")
sets.Name = "Sets"
sets.BackgroundTransparency = 1
sets.Position = UDim2.new(0,0,0,5)
sets.Size = UDim2.new(0.23,0,1,-5)
sets.ZIndex = 6
sets.Parent = setPanel
-- Children of Sets
local line = Instance.new("Frame")
line.Name = "Line"
line.BackgroundColor3 = Color3.new(1,1,1)
line.BackgroundTransparency = 0.7
line.BorderSizePixel = 0
line.Position = UDim2.new(1,-3,0.06,0)
line.Size = UDim2.new(0,3,0.9,0)
line.ZIndex = 6
line.Parent = sets
local setsLists, controlFrame = t.CreateTrueScrollingFrame()
setsLists.Size = UDim2.new(1,-6,0.94,0)
setsLists.Position = UDim2.new(0,0,0.06,0)
setsLists.BackgroundTransparency = 1
setsLists.Name = "SetsLists"
setsLists.ZIndex = 6
setsLists.Parent = sets
drillDownSetZIndex(controlFrame, 7)
local setsHeader = Instance.new("TextLabel")
setsHeader.Name = "SetsHeader"
setsHeader.BackgroundTransparency = 1
setsHeader.Size = UDim2.new(0,47,0,24)
setsHeader.ZIndex = 6
setsHeader.Font = Enum.Font.ArialBold
setsHeader.FontSize = Enum.FontSize.Size24
setsHeader.Text = "Sets"
setsHeader.TextColor3 = Color3.new(1,1,1)
setsHeader.TextXAlignment = Enum.TextXAlignment.Left
setsHeader.TextYAlignment = Enum.TextYAlignment.Top
setsHeader.Parent = sets
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(1,-32,0,-2)
cancelButton.Size = UDim2.new(0,34,0,34)
cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
cancelButton.ZIndex = 6
cancelButton.Text = ""
cancelButton.Modal = true
cancelButton.Parent = setPanel
-- Children of Cancel Button
local cancelImage = Instance.new("ImageLabel")
cancelImage.Name = "CancelImage"
cancelImage.BackgroundTransparency = 1
cancelImage.Image = "http://www.roblox.com/asset/?id=54135717"
cancelImage.Position = UDim2.new(0,-2,0,-2)
cancelImage.Size = UDim2.new(0,16,0,16)
cancelImage.ZIndex = 6
cancelImage.Parent = cancelButton
return setGui
end
local function createSetButton(text)
local setButton = Instance.new("TextButton")
if text then setButton.Text = text
else setButton.Text = "" end
setButton.AutoButtonColor = false
setButton.BackgroundTransparency = 1
setButton.BackgroundColor3 = Color3.new(1,1,1)
setButton.BorderSizePixel = 0
setButton.Size = UDim2.new(1,-5,0,18)
setButton.ZIndex = 6
setButton.Visible = false
setButton.Font = Enum.Font.Arial
setButton.FontSize = Enum.FontSize.Size18
setButton.TextColor3 = Color3.new(1,1,1)
setButton.TextXAlignment = Enum.TextXAlignment.Left
return setButton
end
local function buildSetButton(name, setId, setImageId, i, count)
local button = createSetButton(name)
button.Text = name
button.Name = "SetButton"
button.Visible = true
local setValue = Instance.new("IntValue")
setValue.Name = "SetId"
setValue.Value = setId
setValue.Parent = button
local setName = Instance.new("StringValue")
setName.Name = "SetName"
setName.Value = name
setName.Parent = button
return button
end
local function processCategory(sets)
local setButtons = {}
local numSkipped = 0
for i = 1, #sets do
if not showAdminCategories and sets[i].Name == "Beta" then
numSkipped = numSkipped + 1
else
setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
end
end
return setButtons
end
local function handleResize()
wait() -- neccessary to insure heartbeat happened
local itemPreview = setGui.SetPanel.ItemPreview
itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
end
local function makeInsertAssetButton()
local insertAssetButtonExample = Instance.new("Frame")
insertAssetButtonExample.Name = "InsertAssetButtonExample"
insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
insertAssetButtonExample.BackgroundTransparency = 1
insertAssetButtonExample.ZIndex = 6
insertAssetButtonExample.Visible = false
local assetId = Instance.new("IntValue")
assetId.Name = "AssetId"
assetId.Value = 0
assetId.Parent = insertAssetButtonExample
local assetName = Instance.new("StringValue")
assetName.Name = "AssetName"
assetName.Value = ""
assetName.Parent = insertAssetButtonExample
local button = Instance.new("TextButton")
button.Name = "Button"
button.Text = ""
button.Style = Enum.ButtonStyle.RobloxButton
button.Position = UDim2.new(0.025,0,0.025,0)
button.Size = UDim2.new(0.95,0,0.95,0)
button.ZIndex = 6
button.Parent = insertAssetButtonExample
local buttonImage = Instance.new("ImageLabel")
buttonImage.Name = "ButtonImage"
buttonImage.Image = ""
buttonImage.Position = UDim2.new(0,-7,0,-7)
buttonImage.Size = UDim2.new(1,14,1,14)
buttonImage.BackgroundTransparency = 1
buttonImage.ZIndex = 7
buttonImage.Parent = button
local configIcon = buttonImage:clone()
configIcon.Name = "ConfigIcon"
configIcon.Visible = false
configIcon.Position = UDim2.new(1,-23,1,-24)
configIcon.Size = UDim2.new(0,16,0,16)
configIcon.Image = ""
configIcon.ZIndex = 6
configIcon.Parent = insertAssetButtonExample
return insertAssetButtonExample
end
local function showLargePreview(insertButton)
if insertButton:FindFirstChild("AssetId") then
delay(0,function()
game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
end)
end
if insertButton:FindFirstChild("AssetName") then
setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
end
end
local function selectTerrainShape(shape)
if currTerrainDropDownFrame then
objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
end
end
local function createTerrainTypeButton(name, parent)
local dropDownTextButton = Instance.new("TextButton")
dropDownTextButton.Name = name .. "Button"
dropDownTextButton.Font = Enum.Font.ArialBold
dropDownTextButton.FontSize = Enum.FontSize.Size14
dropDownTextButton.BorderSizePixel = 0
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
dropDownTextButton.Text = name
dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.ZIndex = parent.ZIndex + 1
dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
dropDownTextButton.Position = UDim2.new(0,1,0,0)
dropDownTextButton.MouseEnter:connect(function()
dropDownTextButton.BackgroundTransparency = 0
dropDownTextButton.TextColor3 = Color3.new(0,0,0)
end)
dropDownTextButton.MouseLeave:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
end)
dropDownTextButton.MouseButton1Click:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
dropDownTextButton.Parent.Visible = false
end
selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
end)
return dropDownTextButton
end
local function createTerrainDropDownMenu(zIndex)
local dropDown = Instance.new("Frame")
dropDown.Name = "TerrainDropDown"
dropDown.BackgroundColor3 = Color3.new(0,0,0)
dropDown.BorderColor3 = Color3.new(1,0,0)
dropDown.Size = UDim2.new(0,200,0,0)
dropDown.Visible = false
dropDown.ZIndex = zIndex
dropDown.Parent = setGui
for i = 1, #terrainShapes do
local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
shapeButton.Parent = dropDown
dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
end
dropDown.MouseLeave:connect(function()
dropDown.Visible = false
end)
end
local function createDropDownMenuButton(parent)
local dropDownButton = Instance.new("ImageButton")
dropDownButton.Name = "DropDownButton"
dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509"
dropDownButton.BackgroundTransparency = 1
dropDownButton.Size = UDim2.new(0,16,0,16)
dropDownButton.Position = UDim2.new(1,-24,0,6)
dropDownButton.ZIndex = parent.ZIndex + 2
dropDownButton.Parent = parent
if not setGui:FindFirstChild("TerrainDropDown") then
createTerrainDropDownMenu(8)
end
dropDownButton.MouseButton1Click:connect(function()
setGui.TerrainDropDown.Visible = true
setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
currTerrainDropDownFrame = parent
end)
end
local function buildInsertButton()
local insertButton = makeInsertAssetButton()
insertButton.Name = "InsertAssetButton"
insertButton.Visible = true
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
createDropDownMenuButton(insertButton)
end
local lastEnter = nil
local mouseEnterCon = insertButton.MouseEnter:connect(function()
lastEnter = insertButton
delay(0.1,function()
if lastEnter == insertButton then
showLargePreview(insertButton)
end
end)
end)
return insertButton, mouseEnterCon
end
local function realignButtonGrid(columns)
local x = 0
local y = 0
for i = 1, #insertButtons do
insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
x = x + 1
if x >= columns then
x = 0
y = y + 1
end
end
end
local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
if visible then
insertFrame.AssetName.Value = name
insertFrame.AssetId.Value = assetId
local newImageUrl = SmallThumbnailUrl .. assetId
if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
delay(0,function()
game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
if insertFrame:findFirstChild("Button") then
insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
end
end)
end
table.insert(insertButtonCons,
insertFrame.Button.MouseButton1Click:connect(function()
-- special case for water, show water selection gui
local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
waterGui.Visible = isWaterSelected
if isWaterSelected then
objectSelected(name, tonumber(assetId), nil)
else
objectSelected(name, tonumber(assetId))
end
end)
)
insertFrame.Visible = true
else
insertFrame.Visible = false
end
end
local function loadSectionOfItems(setGui, rows, columns)
local pageSize = rows * columns
if arrayPosition > #contents then return end
local origArrayPos = arrayPosition
local yCopy = 0
for i = 1, pageSize + 1 do
if arrayPosition >= #contents + 1 then
break
end
local buttonCon
insertButtons[arrayPosition], buttonCon = buildInsertButton()
table.insert(insertButtonCons,buttonCon)
insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
arrayPosition = arrayPosition + 1
end
realignButtonGrid(columns)
local indexCopy = origArrayPos
for index = origArrayPos, arrayPosition do
if insertButtons[index] then
if contents[index] then
-- we don't want water to have a drop down button
if contents[index].Name == "Water" then
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
end
end
local assetId
if useAssetVersionId then
assetId = contents[index].AssetVersionId
else
assetId = contents[index].AssetId
end
setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
else
break
end
else
break
end
indexCopy = index
end
end
local function setSetIndex()
Data.Category[Data.CurrentCategory].Index = 0
rows = 7
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
contents = Data.Category[Data.CurrentCategory].Contents
if contents then
-- remove our buttons and their connections
for i = 1, #insertButtons do
insertButtons[i]:remove()
end
for i = 1, #insertButtonCons do
if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
end
insertButtonCons = {}
insertButtons = {}
arrayPosition = 1
loadSectionOfItems(setGui, rows, columns)
end
end
local function selectSet(button, setName, setId, setIndex)
if button and Data.Category[Data.CurrentCategory] ~= nil then
if button ~= Data.Category[Data.CurrentCategory].Button then
Data.Category[Data.CurrentCategory].Button = button
if SetCache[setId] == nil then
SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
end
Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
Data.Category[Data.CurrentCategory].SetName = setName
Data.Category[Data.CurrentCategory].SetId = setId
end
setSetIndex()
end
end
local function selectCategoryPage(buttons, page)
if buttons ~= Data.CurrentCategory then
if Data.CurrentCategory then
for key, button in pairs(Data.CurrentCategory) do
button.Visible = false
end
end
Data.CurrentCategory = buttons
if Data.Category[Data.CurrentCategory] == nil then
Data.Category[Data.CurrentCategory] = {}
if #buttons > 0 then
selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
end
else
Data.Category[Data.CurrentCategory].Button = nil
selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
end
end
end
local function selectCategory(category)
selectCategoryPage(category, 0)
end
local function resetAllSetButtonSelection()
local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
for i = 1, #setButtons do
if setButtons[i]:IsA("TextButton") then
setButtons[i].Selected = false
setButtons[i].BackgroundTransparency = 1
setButtons[i].TextColor3 = Color3.new(1,1,1)
setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
end
end
end
local function populateSetsFrame()
local currRow = 0
for i = 1, #userCategoryButtons do
local button = userCategoryButtons[i]
button.Visible = true
button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
button.Parent = setGui.SetPanel.Sets.SetsLists
if i == 1 then -- we will have this selected by default, so show it
button.Selected = true
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
end
button.MouseEnter:connect(function()
if not button.Selected then
button.BackgroundTransparency = 0
button.TextColor3 = Color3.new(0,0,0)
end
end)
button.MouseLeave:connect(function()
if not button.Selected then
button.BackgroundTransparency = 1
button.TextColor3 = Color3.new(1,1,1)
end
end)
button.MouseButton1Click:connect(function()
resetAllSetButtonSelection()
button.Selected = not button.Selected
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
end)
currRow = currRow + 1
end
local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
-- set first category as loaded for default
if buttons then
for i = 1, #buttons do
if buttons[i]:IsA("TextButton") then
selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
selectCategory(userCategoryButtons)
break
end
end
end
end
setGui = createSetGui()
waterGui, waterTypeChangedEvent = createWaterGui()
waterGui.Position = UDim2.new(0,55,0,0)
waterGui.Parent = setGui
setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
if prop == "AbsoluteSize" then
handleResize()
setSetIndex()
end
end)
local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
scrollFrame.Name = "ItemsFrame"
scrollFrame.ZIndex = 6
scrollFrame.Parent = setGui.SetPanel
scrollFrame.BackgroundTransparency = 1
drillDownSetZIndex(controlFrame,7)
controlFrame.Parent = setGui.SetPanel
controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
local debounce = false
controlFrame.ScrollBottom.Changed:connect(function(prop)
if controlFrame.ScrollBottom.Value == true then
if debounce then return end
debounce = true
loadSectionOfItems(setGui, rows, columns)
debounce = false
end
end)
local userData = {}
for id = 1, #userIdsForSets do
local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
if newUserData and #newUserData > 2 then
-- start at #3 to skip over My Decals and My Models for each account
for category = 3, #newUserData do
if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
table.insert(userData,1,newUserData[category])
else
table.insert(userData, newUserData[category])
end
end
end
end
if userData then
userCategoryButtons = processCategory(userData)
end
rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
populateSetsFrame()
insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
setGui.SetPanel.Visible = false
if dialogClosed then dialogClosed() end
end)
local setVisibilityFunction = function(visible)
if visible then
setGui.SetPanel.Visible = true
else
setGui.SetPanel.Visible = false
end
end
local getVisibilityFunction = function()
if setGui then
if setGui:FindFirstChild("SetPanel") then
return setGui.SetPanel.Visible
end
end
return false
end
return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
end
t.CreateTerrainMaterialSelector = function(size,position)
local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
local selectedButton = nil
local frame = Instance.new("Frame")
frame.Name = "TerrainMaterialSelector"
if size then
frame.Size = size
else
frame.Size = UDim2.new(0, 245, 0, 230)
end
if position then
frame.Position = position
end
frame.BorderSizePixel = 0
frame.BackgroundColor3 = Color3.new(0,0,0)
frame.Active = true
terrainMaterialSelectionChanged.Parent = frame
local waterEnabled = true -- todo: turn this on when water is ready
local materialToImageMap = {}
local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
if waterEnabled then
table.insert(materialNames,"Water")
end
local currentMaterial = 1
function getEnumFromName(choice)
if choice == "Grass" then return 1 end
if choice == "Sand" then return 2 end
if choice == "Erase" then return 0 end
if choice == "Brick" then return 3 end
if choice == "Granite" then return 4 end
if choice == "Asphalt" then return 5 end
if choice == "Iron" then return 6 end
if choice == "Aluminum" then return 7 end
if choice == "Gold" then return 8 end
if choice == "Plank" then return 9 end
if choice == "Log" then return 10 end
if choice == "Gravel" then return 11 end
if choice == "Cinder Block" then return 12 end
if choice == "Stone Wall" then return 13 end
if choice == "Concrete" then return 14 end
if choice == "Plastic (red)" then return 15 end
if choice == "Plastic (blue)" then return 16 end
if choice == "Water" then return 17 end
end
function getNameFromEnum(choice)
if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
if waterEnabled then
if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
end
end
local function updateMaterialChoice(choice)
currentMaterial = getEnumFromName(choice)
terrainMaterialSelectionChanged:Fire(currentMaterial)
end
-- we so need a better way to do this
for i,v in pairs(materialNames) do
materialToImageMap[v] = {}
if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112"
elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652"
elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537"
elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153"
elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038"
elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093"
elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995"
elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118"
elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848"
elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924"
elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015"
elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051"
elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206"
elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103"
elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804"
elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059"
elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474"
else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!!
end
end
local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
scrollFrame.Size = UDim2.new(0.85,0,1,0)
scrollFrame.Position = UDim2.new(0,0,0,0)
scrollFrame.Parent = frame
scrollUp.Parent = frame
scrollUp.Visible = true
scrollUp.Position = UDim2.new(1,-19,0,0)
scrollDown.Parent = frame
scrollDown.Visible = true
scrollDown.Position = UDim2.new(1,-19,1,-17)
local function goToNewMaterial(buttonWrap, materialName)
updateMaterialChoice(materialName)
buttonWrap.BackgroundTransparency = 0
selectedButton.BackgroundTransparency = 1
selectedButton = buttonWrap
end
local function createMaterialButton(name)
local buttonWrap = Instance.new("TextButton")
buttonWrap.Text = ""
buttonWrap.Size = UDim2.new(0,32,0,32)
buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
buttonWrap.BorderSizePixel = 0
buttonWrap.BackgroundTransparency = 1
buttonWrap.AutoButtonColor = false
buttonWrap.Name = tostring(name)
local imageButton = Instance.new("ImageButton")
imageButton.AutoButtonColor = false
imageButton.BackgroundTransparency = 1
imageButton.Size = UDim2.new(0,30,0,30)
imageButton.Position = UDim2.new(0,1,0,1)
imageButton.Name = tostring(name)
imageButton.Parent = buttonWrap
imageButton.Image = materialToImageMap[name].Regular
local enumType = Instance.new("NumberValue")
enumType.Name = "EnumType"
enumType.Parent = buttonWrap
enumType.Value = 0
imageButton.MouseEnter:connect(function()
buttonWrap.BackgroundTransparency = 0
end)
imageButton.MouseLeave:connect(function()
if selectedButton ~= buttonWrap then
buttonWrap.BackgroundTransparency = 1
end
end)
imageButton.MouseButton1Click:connect(function()
if selectedButton ~= buttonWrap then
goToNewMaterial(buttonWrap, tostring(name))
end
end)
return buttonWrap
end
for i = 1, #materialNames do
local imageButton = createMaterialButton(materialNames[i])
if materialNames[i] == "Grass" then -- always start with grass as the default
selectedButton = imageButton
imageButton.BackgroundTransparency = 0
end
imageButton.Parent = scrollFrame
end
local forceTerrainMaterialSelection = function(newMaterialType)
if not newMaterialType then return end
if currentMaterial == newMaterialType then return end
local matName = getNameFromEnum(newMaterialType)
local buttons = scrollFrame:GetChildren()
for i = 1, #buttons do
if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
if string.find(buttons[i].Name, matName) then
goToNewMaterial(buttons[i],matName)
return
end
end
end
frame.Changed:connect(function ( prop )
if prop == "AbsoluteSize" then
recalculateScroll()
end
end)
recalculateScroll()
return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
end
t.CreateLoadingFrame = function(name,size,position)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053")
local loadingFrame = Instance.new("Frame")
loadingFrame.Name = "LoadingFrame"
loadingFrame.Style = Enum.FrameStyle.RobloxRound
if size then loadingFrame.Size = size
else loadingFrame.Size = UDim2.new(0,300,0,160) end
if position then loadingFrame.Position = position
else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
local loadingBar = Instance.new("Frame")
loadingBar.Name = "LoadingBar"
loadingBar.BackgroundColor3 = Color3.new(0,0,0)
loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
loadingBar.Position = UDim2.new(0,0,0,41)
loadingBar.Size = UDim2.new(1,0,0,30)
loadingBar.Parent = loadingFrame
local loadingGreenBar = Instance.new("ImageLabel")
loadingGreenBar.Name = "LoadingGreenBar"
loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053"
loadingGreenBar.Position = UDim2.new(0,0,0,0)
loadingGreenBar.Size = UDim2.new(0,0,1,0)
loadingGreenBar.Visible = false
loadingGreenBar.Parent = loadingBar
local loadingPercent = Instance.new("TextLabel")
loadingPercent.Name = "LoadingPercent"
loadingPercent.BackgroundTransparency = 1
loadingPercent.Position = UDim2.new(0,0,1,0)
loadingPercent.Size = UDim2.new(1,0,0,14)
loadingPercent.Font = Enum.Font.Arial
loadingPercent.Text = "0%"
loadingPercent.FontSize = Enum.FontSize.Size14
loadingPercent.TextColor3 = Color3.new(1,1,1)
loadingPercent.Parent = loadingBar
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(0.5,-60,1,-40)
cancelButton.Size = UDim2.new(0,120,0,40)
cancelButton.Font = Enum.Font.Arial
cancelButton.FontSize = Enum.FontSize.Size18
cancelButton.TextColor3 = Color3.new(1,1,1)
cancelButton.Text = "Cancel"
cancelButton.Style = Enum.ButtonStyle.RobloxButton
cancelButton.Parent = loadingFrame
local loadingName = Instance.new("TextLabel")
loadingName.Name = "loadingName"
loadingName.BackgroundTransparency = 1
loadingName.Size = UDim2.new(1,0,0,18)
loadingName.Position = UDim2.new(0,0,0,2)
loadingName.Font = Enum.Font.Arial
loadingName.Text = name
loadingName.TextColor3 = Color3.new(1,1,1)
loadingName.TextStrokeTransparency = 1
loadingName.FontSize = Enum.FontSize.Size18
loadingName.Parent = loadingFrame
local cancelButtonClicked = Instance.new("BindableEvent")
cancelButtonClicked.Name = "CancelButtonClicked"
cancelButtonClicked.Parent = cancelButton
cancelButton.MouseButton1Click:connect(function()
cancelButtonClicked:Fire()
end)
local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
if percent and type(percent) ~= "number" then
error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
end
local newSize = nil
if percent < 0 then
newSize = UDim2.new(0,0,1,0)
elseif percent > 1 then
newSize = UDim2.new(1,0,1,0)
else
newSize = UDim2.new(percent,0,1,0)
end
if tweenAction then
if not tweenLength then
error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
end
if (newSize.X.Scale > 0) then
loadingGreenBar.Visible = true
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true)
else
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true,
function()
if (newSize.X.Scale < 0) then
loadingGreenBar.Visible = false
end
end)
end
else
loadingGreenBar.Size = newSize
loadingGreenBar.Visible = (newSize.X.Scale > 0)
end
end
loadingGreenBar.Changed:connect(function(prop)
if prop == "Size" then
loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
end
end)
return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
end
t.CreatePluginFrame = function (name,size,position,scrollable,parent)
function createMenuButton(size,position,text,fontsize,name,parent)
local button = Instance.new("TextButton",parent)
button.AutoButtonColor = false
button.Name = name
button.BackgroundTransparency = 1
button.Position = position
button.Size = size
button.Font = Enum.Font.ArialBold
button.FontSize = fontsize
button.Text = text
button.TextColor3 = Color3.new(1,1,1)
button.BorderSizePixel = 0
button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
button.MouseEnter:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 1
end)
return button
end
local dragBar = Instance.new("Frame",parent)
dragBar.Name = tostring(name) .. "DragBar"
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
dragBar.BorderColor3 = Color3.new(0,0,0)
if size then
dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
else
dragBar.Size = UDim2.new(0,183,0,20)
end
if position then
dragBar.Position = position
end
dragBar.Active = true
dragBar.Draggable = true
--dragBar.Visible = false
dragBar.MouseEnter:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
end)
dragBar.MouseLeave:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end)
-- plugin name label
local pluginNameLabel = Instance.new("TextLabel",dragBar)
pluginNameLabel.Name = "BarNameLabel"
pluginNameLabel.Text = " " .. tostring(name)
pluginNameLabel.TextColor3 = Color3.new(1,1,1)
pluginNameLabel.TextStrokeTransparency = 0
pluginNameLabel.Size = UDim2.new(1,0,1,0)
pluginNameLabel.Font = Enum.Font.ArialBold
pluginNameLabel.FontSize = Enum.FontSize.Size18
pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
pluginNameLabel.BackgroundTransparency = 1
-- close button
local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
local closeEvent = Instance.new("BindableEvent")
closeEvent.Name = "CloseEvent"
closeEvent.Parent = closeButton
closeButton.MouseButton1Click:connect(function ()
closeEvent:Fire()
closeButton.BackgroundTransparency = 1
end)
-- help button
local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
local helpFrame = Instance.new("Frame",dragBar)
helpFrame.Name = "HelpFrame"
helpFrame.BackgroundColor3 = Color3.new(0,0,0)
helpFrame.Size = UDim2.new(0,300,0,552)
helpFrame.Position = UDim2.new(1,5,0,0)
helpFrame.Active = true
helpFrame.BorderSizePixel = 0
helpFrame.Visible = false
helpButton.MouseButton1Click:connect(function( )
helpFrame.Visible = not helpFrame.Visible
if helpFrame.Visible then
helpButton.Selected = true
helpButton.BackgroundTransparency = 0
local screenGui = getScreenGuiAncestor(helpFrame)
if screenGui then
if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
else -- position on right hand side
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpButton.Selected = false
helpButton.BackgroundTransparency = 1
end
end)
local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
local minimizeFrame = Instance.new("Frame",dragBar)
minimizeFrame.Name = "MinimizeFrame"
minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
minimizeFrame.BorderColor3 = Color3.new(0,0,0)
minimizeFrame.Position = UDim2.new(0,0,1,0)
if size then
minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
else
minimizeFrame.Size = UDim2.new(0,183,0,50)
end
minimizeFrame.Visible = false
local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
minimizeBigButton.Name = "MinimizeButton"
minimizeBigButton.Size = UDim2.new(0,100,0,40)
minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
minimizeBigButton.Font = Enum.Font.ArialBold
minimizeBigButton.FontSize = Enum.FontSize.Size18
minimizeBigButton.TextColor3 = Color3.new(1,1,1)
minimizeBigButton.Text = "Show"
local separatingLine = Instance.new("Frame",dragBar)
separatingLine.Name = "SeparatingLine"
separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
separatingLine.BorderSizePixel = 0
separatingLine.Position = UDim2.new(1,-18,0.5,-7)
separatingLine.Size = UDim2.new(0,1,0,14)
local otherSeparatingLine = separatingLine:clone()
otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
otherSeparatingLine.Parent = dragBar
local widgetContainer = Instance.new("Frame",dragBar)
widgetContainer.Name = "WidgetContainer"
widgetContainer.BackgroundTransparency = 1
widgetContainer.Position = UDim2.new(0,0,1,0)
widgetContainer.BorderColor3 = Color3.new(0,0,0)
if not scrollable then
widgetContainer.BackgroundTransparency = 0
widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
end
if size then
if scrollable then
widgetContainer.Size = size
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
end
else
if scrollable then
widgetContainer.Size = UDim2.new(0,163,0,400)
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
end
end
if position then
widgetContainer.Position = position + UDim2.new(0,0,0,20)
end
local frame,control,verticalDragger = nil
if scrollable then
--frame for widgets
frame,control = t.CreateTrueScrollingFrame()
frame.Size = UDim2.new(1, 0, 1, 0)
frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
frame.BorderColor3 = Color3.new(0,0,0)
frame.Active = true
frame.Parent = widgetContainer
control.Parent = dragBar
control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
control.BorderSizePixel = 0
control.BackgroundTransparency = 0
control.Position = UDim2.new(1,-21,1,1)
if size then
control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
else
control.Size = UDim2.new(0,21,0,400)
end
control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
local fakeLine = Instance.new("Frame",control)
fakeLine.Name = "FakeLine"
fakeLine.BorderSizePixel = 0
fakeLine.BackgroundColor3 = Color3.new(0,0,0)
fakeLine.Size = UDim2.new(0,1,1,1)
fakeLine.Position = UDim2.new(1,0,0,0)
verticalDragger = Instance.new("TextButton",widgetContainer)
verticalDragger.ZIndex = 2
verticalDragger.AutoButtonColor = false
verticalDragger.Name = "VerticalDragger"
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
verticalDragger.BorderColor3 = Color3.new(0,0,0)
verticalDragger.Size = UDim2.new(1,20,0,20)
verticalDragger.Position = UDim2.new(0,0,1,0)
verticalDragger.Active = true
verticalDragger.Text = ""
local scrubFrame = Instance.new("Frame",verticalDragger)
scrubFrame.Name = "ScrubFrame"
scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
scrubFrame.BorderSizePixel = 0
scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
scrubFrame.Size = UDim2.new(0,10,0,1)
scrubFrame.ZIndex = 5
local scrubTwo = scrubFrame:clone()
scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
scrubTwo.Parent = verticalDragger
local scrubThree = scrubFrame:clone()
scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
scrubThree.Parent = verticalDragger
local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
areaSoak.Name = "AreaSoak"
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.BackgroundTransparency = 1
areaSoak.BorderSizePixel = 0
areaSoak.Text = ""
areaSoak.ZIndex = 10
areaSoak.Visible = false
areaSoak.Active = true
local draggingVertical = false
local startYPos = nil
verticalDragger.MouseEnter:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
end)
verticalDragger.MouseLeave:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
end)
verticalDragger.MouseButton1Down:connect(function(x,y)
draggingVertical = true
areaSoak.Visible = true
startYPos = y
end)
areaSoak.MouseButton1Up:connect(function ( )
draggingVertical = false
areaSoak.Visible = false
end)
areaSoak.MouseMoved:connect(function(x,y)
if not draggingVertical then return end
local yDelta = y - startYPos
if not control.ScrollDownButton.Visible and yDelta > 0 then
return
end
if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
control.Size = UDim2.new (0,21,0,150)
return
end
startYPos = y
if widgetContainer.Size.Y.Offset + yDelta >= 0 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
end
end)
end
local function switchMinimize()
minimizeFrame.Visible = not minimizeFrame.Visible
if scrollable then
frame.Visible = not frame.Visible
verticalDragger.Visible = not verticalDragger.Visible
control.Visible = not control.Visible
else
widgetContainer.Visible = not widgetContainer.Visible
end
if minimizeFrame.Visible then
minimizeButton.Text = "+"
else
minimizeButton.Text = "-"
end
end
minimizeBigButton.MouseButton1Click:connect(function ( )
switchMinimize()
end)
minimizeButton.MouseButton1Click:connect(function( )
switchMinimize()
end)
if scrollable then
return dragBar, frame, helpFrame, closeEvent
else
return dragBar, widgetContainer, helpFrame, closeEvent
end
end
t.Help =
function(funcNameOrFunc)
--input argument can be a string or a function. Should return a description (of arguments and expected side effects)
if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
return "Function CreatePropertyDropDownMenu. " ..
"Arguments: (instance, propertyName, enumType). " ..
"Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
end
if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
return "Function CreateDropDownMenu. " ..
"Arguments: (items, onItemSelected). " ..
"Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
end
if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
return "Function CreateMessageDialog. " ..
"Arguments: (title, message, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
end
if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
return "Function CreateStyledMessageDialog. " ..
"Arguments: (title, message, style, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
end
if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
return "Function GetFontHeight. " ..
"Arguments: (font, fontSize). " ..
"Side effect: returns the size in pixels of the given font + fontSize"
end
if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
end
if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
return "Function CreateScrollingFrame. " ..
"Arguments: (orderList, style) " ..
"Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
end
if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
return "Function CreateTrueScrollingFrame. " ..
"Arguments: (nil) " ..
"Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
end
if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
return "Function AutoTruncateTextObject. " ..
"Arguments: (textLabel) " ..
"Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
end
if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
return "Function CreateSlider. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then
return "Function CreateSliderNew. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
return "Function CreateLoadingFrame. " ..
"Arguments: (name, size, position) " ..
"Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
end
if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
return "Function CreateTerrainMaterialSelector. " ..
"Arguments: (size, position) " ..
"Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
end
end
-- A couple of necessary functions
local function waitForChild(instance, name)
assert(instance)
assert(name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
assert(instance)
assert(property)
while not instance[property] do
instance.Changed:wait()
end
end
local function IsTouchDevice()
--return Game:GetService('UserInputService').TouchEnabled
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
local RbxGui, msg = t
if not RbxGui then print("could not find RbxGui!") return end
--- Begin Locals
local StaticTabName = "gear"
local backpack = script.Parent.Backpack
local screen = script.Parent
local backpackItems = {}
local buttons = {}
local debounce = false
local browsingMenu = false
local mouseEnterCons = {}
local mouseClickCons = {}
local characterChildAddedCon = nil
local characterChildRemovedCon = nil
local backpackAddCon = nil
local playerBackpack = waitForChild(player,"Backpack")
waitForChild(backpack,"Gear")
local gearPreview = waitForChild(backpack.Gear,"GearPreview")
local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea")
local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout")
local grid = waitForChild(backpack.Gear,"GearGrid")
local gearButton = waitForChild(grid,"GearButton")
local swapSlot = waitForChild(script.Parent,"SwapSlot")
local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager")
local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent")
local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent")
local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent")
local resizeEvent = waitForChild(backpackManager,"ResizeEvent")
local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent")
local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady")
-- creating scroll bar early as to make sure items get placed correctly
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(6, 6))
scrollFrame.Position = UDim2.new(0,0,0,30)
scrollFrame.Size = UDim2.new(1,0,1,-30)
scrollFrame.Parent = backpack.Gear.GearGrid
local scrollBar = Instance.new("Frame")
scrollBar.Name = "ScrollBar"
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
scrollBar.Position = UDim2.new(0,0,0,18)
scrollBar.Parent = scroller
scrollDown.Position = UDim2.new(0,0,1,-17)
scrollUp.Parent = scroller
scrollDown.Parent = scroller
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
local LoadoutButton = Instance.new("TextButton")
LoadoutButton.Name = "LoadoutButton"
LoadoutButton.Font = Enum.Font.ArialBold
LoadoutButton.FontSize = Enum.FontSize.Size14
LoadoutButton.Position = UDim2.new(0,0,0,0)
LoadoutButton.Size = UDim2.new(1,0,0,32)
LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
LoadoutButton.Text = "Loadout #1"
LoadoutButton.TextColor3 = Color3.new(1,1,1)
LoadoutButton.Parent = scrollFrameLoadout
local LoadoutButtonTwo = LoadoutButton:clone()
LoadoutButtonTwo.Text = "Loadout #2"
LoadoutButtonTwo.Parent = scrollFrameLoadout
local LoadoutButtonThree = LoadoutButton:clone()
LoadoutButtonThree.Text = "Loadout #3"
LoadoutButtonThree.Parent = scrollFrameLoadout
local LoadoutButtonFour = LoadoutButton:clone()
LoadoutButtonFour.Text = "Loadout #4"
LoadoutButtonFour.Parent = scrollFrameLoadout
local scrollBarLoadout = Instance.new("Frame")
scrollBarLoadout.Name = "ScrollBarLoadout"
scrollBarLoadout.BackgroundTransparency = 0.9
scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
scrollBarLoadout.BorderSizePixel = 0
scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
scrollBarLoadout.Position = UDim2.new(0,0,0,18)
scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
-- Begin Functions
function removeFromMap(map,object)
for i = 1, #map do
if map[i] == object then
table.remove(map,i)
break
end
end
end
function robloxLock(instance)
end
function resize()
local size = 0
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
size = gearPreview.AbsoluteSize.X * 0.75
else
size = gearPreview.AbsoluteSize.Y * 0.75
end
waitForChild(gearPreview,"GearImage")
gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
resizeGrid()
end
function addToGrid(child)
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
return
end
end
if child:FindFirstChild("RobloxBuildTool") then return end
for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
if v == child then return end
end
table.insert(backpackItems,child)
local changeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if buttons[child] then
if buttons[child].Image == "" then
buttons[child].GearText.Text = child.Name
end
end
end
end)
local ancestryCon = nil
ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
local thisObject = nil
for k,v in pairs(backpackItems) do
if v == child then
thisObject = v
break
end
end
waitForProperty(player,"Character")
waitForChild(player,"Backpack")
if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
if ancestryCon then ancestryCon:disconnect() end
if changeCon then changeCon:disconnect() end
for k,v in pairs(backpackItems) do
if v == thisObject then
if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
buttons[v].Parent = nil
buttons[v] = nil
break
end
end
removeFromMap(backpackItems,thisObject)
resizeGrid()
else
resizeGrid()
end
updateGridActive()
end)
resizeGrid()
end
function buttonClick(button)
if button:FindFirstChild("UnequipContextMenu") and not button.Active then
button.UnequipContextMenu.Visible = true
browsingMenu = true
end
end
function previewGear(button)
if not browsingMenu then
gearPreview.Visible = false
gearPreview.GearImage.Image = button.Image
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
end
end
function findEmptySlot()
local smallestNum = nil
local loadout = currentLoadout:GetChildren()
for i = 1, #loadout do
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
local frameNum = tonumber(string.sub(loadout[i].Name,5))
if frameNum == 0 then frameNum = 10 end
if not smallestNum or (smallestNum > frameNum) then
smallestNum = frameNum
end
end
end
if smallestNum == 10 then smallestNum = 0 end
return smallestNum
end
function checkForSwap(button,x,y)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
swapGearSlot(slot,button)
return true
end
end
end
end
return false
end
function resizeGrid()
for k,v in pairs(backpackItems) do
if not v:FindFirstChild("RobloxBuildTool") then
if not buttons[v] then
local buttonClone = gearButton:clone()
buttonClone.Parent = grid.ScrollingFrame
buttonClone.Visible = true
buttonClone.Image = v.TextureId
if buttonClone.Image == "" then
buttonClone.GearText.Text = v.Name
end
buttonClone.GearReference.Value = v
buttonClone.Draggable = true
buttons[v] = buttonClone
if not IsTouchDevice() then
local unequipMenu = getGearContextMenu()
unequipMenu.Visible = false
unequipMenu.Parent = buttonClone
end
local beginPos = nil
buttonClone.DragBegin:connect(function(value)
waitForChild(buttonClone, 'Background')
buttonClone['Background'].ZIndex = 10
buttonClone.ZIndex = 10
beginPos = value
end)
buttonClone.DragStopped:connect(function(x,y)
waitForChild(buttonClone, 'Background')
buttonClone['Background'].ZIndex = 1.0
buttonClone.ZIndex = 2
if beginPos ~= buttonClone.Position then
if not checkForSwap(buttonClone,x,y) then
buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
buttonClone.Draggable = false
delay(0.5,function()
buttonClone.Draggable = true
end)
else
buttonClone.Position = beginPos
end
end
end)
local clickTime = tick()
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
local newClickTime = tick()
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
local slot = findEmptySlot()
if slot then
buttonClone.ZIndex = 1
swapGearSlot(slot,buttonClone)
end
else
buttonClick(buttonClone)
end
clickTime = newClickTime
end)
end
end
end
recalculateScroll()
end
function showPartialGrid(subset)
for k,v in pairs(buttons) do
v.Parent = nil
end
if subset then
for k,v in pairs(subset) do
v.Parent = grid.ScrollingFrame
end
end
recalculateScroll()
end
function showEntireGrid()
for k,v in pairs(buttons) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function inLoadout(gear)
local children = currentLoadout:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
local button = children[i]:GetChildren()
if #button > 0 then
if button[1].GearReference.Value and button[1].GearReference.Value == gear then
return true
end
end
end
end
return false
end
function updateGridActive()
for k,v in pairs(backpackItems) do
if buttons[v] then
local gear = nil
local gearRef = buttons[v]:FindFirstChild("GearReference")
if gearRef then gear = gearRef.Value end
if not gear then
buttons[v].Active = false
elseif inLoadout(gear) then
buttons[v].Active = false
else
buttons[v].Active = true
end
end
end
end
function centerGear(loadoutChildren)
local gearButtons = {}
local lastSlotAdd = nil
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function tabClickHandler(tabName)
if tabName == StaticTabName then
backpackOpenHandler(tabName)
else
backpackCloseHandler(tabName)
end
end
function backpackOpenHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = true
updateGridActive()
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function backpackCloseHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = false
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function loadoutCheck(child, selectState)
if not child:IsA("ImageButton") then return end
for k,v in pairs(backpackItems) do
if buttons[v] then
if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
if buttons[v].GearReference.Value == child.GearReference.Value then
buttons[v].Active = selectState
break
end
end
end
end
end
function clearPreview()
gearPreview.GearImage.Image = ""
gearPreview.GearStats.GearName.Text = ""
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
stuff[i].Parent = playerBackpack
end
end
end
function equipGear(physGear)
removeAllEquippedGear(physGear)
physGear.Parent = player.Character
updateGridActive()
end
function unequipGear(physGear)
physGear.Parent = playerBackpack
updateGridActive()
end
function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
function swapGearSlot(slot,gearButton)
if not swapSlot.Value then -- signal loadout to swap a gear out
swapSlot.Slot.Value = slot
swapSlot.GearButton.Value = gearButton
swapSlot.Value = true
updateGridActive()
end
end
local UnequipGearMenuClick = function(element, menu)
if type(element.Action) ~= "number" then return end
local num = element.Action
if num == 1 then -- remove from loadout
unequipGear(menu.Parent.GearReference.Value)
local inventoryButton = menu.Parent
local gearToUnequip = inventoryButton.GearReference.Value
local loadoutChildren = currentLoadout:GetChildren()
local slot = -1
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local button = loadoutChildren[i]:GetChildren()
if button[1] and button[1].GearReference.Value == gearToUnequip then
slot = button[1].SlotNumber.Text
break
end
end
end
swapGearSlot(slot,nil)
end
end
function setupCharacterConnections()
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
-- make sure we get all the children
local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
if characterChildAddedCon then characterChildAddedCon:disconnect() end
characterChildAddedCon =
game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
addToGrid(child)
updateGridActive()
end)
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
characterChildRemovedCon =
game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
updateGridActive()
end)
wait()
centerGear(currentLoadout:GetChildren())
end
function removeCharacterConnections()
if characterChildAddedCon then characterChildAddedCon:disconnect() end
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
if backpackAddCon then backpackAddCon:disconnect() end
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function filterGear(terms)
local filteredGear = {}
for k,v in pairs(backpackItems) do
if buttons[v] then
local gearString = string.lower(buttons[v].GearReference.Value.Name)
gearString = trim(gearString)
for i = 1, #terms do
if string.match(gearString,terms[i]) then
table.insert(filteredGear,buttons[v])
break
end
end
end
end
return filteredGear
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function showSearchGear(searchTerms)
if not backpack.Gear.Visible then return end -- currently not active tab
local searchTermTable = splitByWhitespace(searchTerms)
if searchTermTable and (#searchTermTable > 0) then
currSearchTerms = searchTermTable
else
currSearchTerms = nil
end
if searchTermTable == nil then
showEntireGrid()
return
end
local filteredButtons = filterGear(currSearchTerms)
showPartialGrid(filteredButtons)
end
function nukeBackpack()
while #buttons > 0 do
table.remove(buttons)
end
buttons = {}
while #backpackItems > 0 do
table.remove(backpackItems)
end
backpackItems = {}
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
for i = 1, #scrollingFrameChildren do
scrollingFrameChildren[i]:remove()
end
end
function getGearContextMenu()
local gearContextMenu = Instance.new("Frame")
gearContextMenu.Active = true
gearContextMenu.Name = "UnequipContextMenu"
gearContextMenu.Size = UDim2.new(0,115,0,70)
gearContextMenu.Position = UDim2.new(0,-16,0,-16)
gearContextMenu.BackgroundTransparency = 1
gearContextMenu.Visible = false
local gearContextMenuButton = Instance.new("TextButton")
gearContextMenuButton.Name = "UnequipContextMenuButton"
gearContextMenuButton.Text = ""
gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
gearContextMenuButton.ZIndex = 8
gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
gearContextMenuButton.Visible = true
gearContextMenuButton.Parent = gearContextMenu
local elementHeight = 12
local contextMenuElements = {}
local contextMenuElementsName = {"Remove Hotkey"}
for i = 1, #contextMenuElementsName do
local element = {}
element.Type = "Button"
element.Text = contextMenuElementsName[i]
element.Action = i
element.DoIt = UnequipGearMenuClick
table.insert(contextMenuElements,element)
end
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == "Button" then
local button = Instance.new("TextButton")
button.Name = "UnequipContextButton" .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = " " .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.Position = UDim2.new(0,0,0,elementHeight * i)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 9
button.Parent = gearContextMenuButton
if not IsTouchDevice() then
button.MouseButton1Click:connect(function()
if button.Active and not gearContextMenu.Parent.Active then
local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
browsingMenu = false
gearContextMenu.Visible = false
clearHighlight(button)
clearPreview()
end
end)
button.MouseEnter:connect(function()
if button.Active and gearContextMenu.Parent.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active and gearContextMenu.Parent.Active then
clearHighlight(button)
end
end)
end
contextElement.Button = button
contextElement.Element = button
elseif element.Type == "Label" then
local frame = Instance.new("Frame")
frame.Name = "ContextLabel" .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new("TextLabel")
label.Name = "Text1"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.0, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label1 = label
if element.GetText2 then
label = Instance.new("TextLabel")
label.Name = "Text2"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Right
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.5, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label2 = label
end
frame.Parent = gearContextMenuButton
element.Label = frame
element.Element = frame
end
end
gearContextMenu.ZIndex = 4
gearContextMenu.MouseLeave:connect(function()
browsingMenu = false
gearContextMenu.Visible = false
clearPreview()
end)
return gearContextMenu
end
function coreGuiChanged(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
if not enabled then
backpack.Gear.Visible = false
end
end
end
local backpackChildren = player.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
------------------------- Start Lifelong Connections -----------------------
resizeEvent.Event:connect(function(absSize)
if debounce then return end
debounce = true
wait()
resize()
resizeGrid()
debounce = false
end)
currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
currentLoadout.DescendantAdded:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
centerGear(currentLoadout:GetChildren())
end
end)
currentLoadout.DescendantRemoving:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
wait()
centerGear(currentLoadout:GetChildren())
end
end)
grid.MouseEnter:connect(function() clearPreview() end)
grid.MouseLeave:connect(function() clearPreview() end)
player.CharacterRemoving:connect(function()
removeCharacterConnections()
nukeBackpack()
end)
player.CharacterAdded:connect(function() setupCharacterConnections() end)
player.ChildAdded:connect(function(child)
if child:IsA("Backpack") then
playerBackpack = child
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
end)
swapSlot.Changed:connect(function()
if not swapSlot.Value then
updateGridActive()
end
end)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
loadoutChildren[i].ChildRemoved:connect(function()
updateGridActive()
end)
loadoutChildren[i].ChildAdded:connect(function()
updateGridActive()
end)
end
end
------------------------- End Lifelong Connections -----------------------
resize()
resizeGrid()
-- make sure any items in the loadout are accounted for in inventory
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
loadoutCheck(loadoutChildren[i], false)
end
if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
-- make sure that inventory is listening to gear reparenting
if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
setupCharacterConnections()
end
if not backpackAddCon then
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
backpackOpenEvent.Event:connect(backpackOpenHandler)
backpackCloseEvent.Event:connect(backpackCloseHandler)
tabClickedEvent.Event:connect(tabClickHandler)
searchRequestedEvent.Event:connect(showSearchGear)
recalculateScrollLoadout()
-
false
BackpackManager
-- basic functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
-- don't do anything if we are in an empty game
waitForChild(game,"Players")
if #game.Players:GetChildren() < 1 then
game.Players.ChildAdded:wait()
end
-- make sure everything is loaded in before we do anything
-- get our local player
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
------------------------ Locals ------------------------------
local backpack = script.Parent.Backpack
waitForChild(backpack,"Gear")
local screen = script.Parent
assert(screen:IsA("ScreenGui"))
waitForChild(backpack.Parent,"ControlFrame")
local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
local currentTab = "gear"
local searchFrame = waitForChild(backpack,"SearchFrame")
waitForChild(backpack.SearchFrame,"SearchBoxFrame")
local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox")
local searchButton = waitForChild(backpack.SearchFrame,"SearchButton")
local resetButton = waitForChild(backpack.SearchFrame,"ResetButton")
local robloxGui = script.Parent
local currentLoadout = waitForChild(robloxGui, 'CurrentLoadout')
local loadoutBackground = waitForChild(currentLoadout, 'Background')
local canToggle = true
local readyForNextEvent = true
local backpackIsOpen = false
local active = true
local humanoidDiedCon = nil
local backpackButtonPos
local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack
local searchDefaultText = "Search..."
local tilde = "~"
local backquote = "`"
local backpackSize = UDim2.new(0, 600, 0, 400)
------------------------ End Locals ---------------------------
---------------------------------------- Public Event Setup ----------------------------------------
function createPublicEvent(eventName)
assert(eventName, "eventName is nil")
assert(tostring(eventName),"eventName is not a string")
local newEvent = Instance.new("BindableEvent")
newEvent.Name = tostring(eventName)
newEvent.Parent = script
return newEvent
end
function createPublicFunction(funcName, invokeFunc)
assert(funcName, "funcName is nil")
assert(tostring(funcName), "funcName is not a string")
assert(invokeFunc, "invokeFunc is nil")
assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'")
local newFunction = Instance.new("BindableFunction")
newFunction.Name = tostring(funcName)
newFunction.OnInvoke = invokeFunc
newFunction.Parent = script
return newFunction
end
-- Events
local resizeEvent = createPublicEvent("ResizeEvent")
local backpackOpenEvent = createPublicEvent("BackpackOpenEvent")
local backpackCloseEvent = createPublicEvent("BackpackCloseEvent")
local tabClickedEvent = createPublicEvent("TabClickedEvent")
local searchRequestedEvent = createPublicEvent("SearchRequestedEvent")
---------------------------------------- End Public Event Setup ----------------------------------------
--------------------------- Internal Functions ----------------------------------------
function deactivateBackpack()
backpack.Visible = false
active = false
end
function activateBackpack()
initHumanoidDiedConnections()
active = true
backpack.Visible = backpackIsOpen
if backpackIsOpen then
toggleBackpack()
end
end
function initHumanoidDiedConnections()
if humanoidDiedCon then
humanoidDiedCon:disconnect()
end
waitForProperty(game.Players.LocalPlayer,"Character")
waitForChild(game.Players.LocalPlayer.Character,"Humanoid")
humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack)
end
local hideBackpack = function()
backpackIsOpen = false
readyForNextEvent = false
backpackButton.Selected = false
resetSearch()
backpackCloseEvent:Fire(currentTab)
searchFrame.Visible = false
backpack:TweenSizeAndPosition(UDim2.new(0, backpackSize.X.Offset,0, 0), UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -85), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true,
function()
game.GuiService:RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
end)
delay(guiTweenSpeed,function()
--game.GuiService:RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
readyForNextEvent = true
canToggle = true
end)
end
function spreadOutGear(loadoutChildren)
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
if slot == 0 then slot = 10 end
loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
end
function showBackpack()
game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
backpack.Visible = true
backpackButton.Selected = true
end,
function()
backpack.Visible = false
backpackButton.Selected = false
end)
backpack.Visible = true
backpack.Gear.Visible = true
backpackButton.Selected = true
backpack:TweenSizeAndPosition(backpackSize, UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -backpackSize.Y.Offset - 88), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true)
delay(guiTweenSpeed,function()
searchFrame.Visible = true
--backpackOpenEvent:Fire(currentTab)
canToggle = true
readyForNextEvent = true
backpackButton.Image = 'http://www.roblox.com/asset/?id=97644093'
backpackButton.Position = UDim2.new(0.5, -60, 1, -backpackSize.Y.Offset - 103)
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 0.5
end
end
spreadOutGear(loadoutChildren)
end)
end
function toggleBackpack()
if not game.Players.LocalPlayer then return end
if not game.Players.LocalPlayer["Character"] then return end
if not canToggle then return end
if not readyForNextEvent then return end
readyForNextEvent = false
canToggle = false
backpackIsOpen = not backpackIsOpen
if backpackIsOpen then
loadoutBackground.Image = 'http://www.roblox.com/asset/?id=97623721'
loadoutBackground.Position = UDim2.new(-0.03, 0, -0.17, 0)
loadoutBackground.Size = UDim2.new(1.05, 0, 1.25, 0)
loadoutBackground.ZIndex = 2.0
loadoutBackground.Visible = true
backpackButton.Position = UDim2.new(0.5, -60, 1, -503)
showBackpack()
else
backpackButton.Position = UDim2.new(0.5, -60, 1, -44)
loadoutBackground.Visible = false
backpackButton.Selected = false
backpackButton.Image = "http://www.roblox.com/asset/?id=97617958"
loadoutBackground.Image = 'http://www.roblox.com/asset/?id=96536002'
loadoutBackground.Position = UDim2.new(-0.1, 0, -0.1, 0)
loadoutBackground.Size = UDim2.new(1.2, 0, 1.2, 0)
hideBackpack()
local clChildren = currentLoadout:GetChildren()
for i = 1, #clChildren do
if clChildren[i] and clChildren[i]:IsA('Frame') then
local frame = clChildren[i]
if #frame:GetChildren() > 0 then
backpackButton.Position = UDim2.new(0.5, -60, 1, -108)
backpackButton.Visible = true
loadoutBackground.Visible = true
if frame:GetChildren()[1]:IsA('ImageButton') then
local imgButton = frame:GetChildren()[1]
imgButton.Active = true
imgButton.Draggable = false
end
end
end
end
end
end
function closeBackpack()
if backpackIsOpen then
toggleBackpack()
end
end
function setSelected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(1,1,1)
tab.TextColor3 = Color3.new(0,0,0)
tab.Selected = true
tab.ZIndex = 3
end
function setUnselected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(0,0,0)
tab.TextColor3 = Color3.new(1,1,1)
tab.Selected = false
tab.ZIndex = 1
end
function updateTabGui(selectedTab)
assert(selectedTab)
if selectedTab == "gear" then
elseif selectedTab == "wardrobe" then
end
end
function mouseLeaveTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(0,0,0)
end
function mouseOverTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end
function newTabClicked(tabName)
assert(tabName)
tabName = string.lower(tabName)
currentTab = tabName
updateTabGui(tabName)
tabClickedEvent:Fire(tabName)
resetSearch()
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function resetSearchBoxGui()
resetButton.Visible = false
searchBox.Text = searchDefaultText
end
function doSearch()
local searchText = searchBox.Text
if searchText == "" then
resetSearch()
return
end
searchText = trim(searchText)
resetButton.Visible = true
termTable = splitByWhitespace(searchText)
searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible
end
function resetSearch()
resetSearchBoxGui()
searchRequestedEvent:Fire()
end
local backpackReady = function()
readyForNextEvent = true
end
--------------------------- End Internal Functions -------------------------------------
------------------------------ Public Functions Setup -------------------------------------
createPublicFunction("CloseBackpack", hideBackpack)
createPublicFunction("BackpackReady", backpackReady)
------------------------------ End Public Functions Setup ---------------------------------
------------------------ Connections/Script Main -------------------------------------------
screen.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
resizeEvent:Fire(screen.AbsoluteSize)
end
end)
-- GuiService key setup
game:GetService("GuiService"):AddKey(tilde)
game:GetService("GuiService"):AddKey(backquote)
game:GetService("GuiService").KeyPressed:connect(function(key)
if not active then return end
if key == tilde or key == backquote then
toggleBackpack()
showBackpack()
end
end)
backpackButton.MouseButton1Click:connect(function()
if not active then return end
toggleBackpack()
end)
if game.Players.LocalPlayer["Character"] then
activateBackpack()
end
game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack)
-- search functions
searchBox.FocusLost:connect(function(enterPressed)
if enterPressed or searchBox.Text ~= "" then
doSearch()
elseif searchBox.Text == "" then
resetSearch()
end
end)
searchButton.MouseButton1Click:connect(doSearch)
resetButton.MouseButton1Click:connect(resetSearch)
--backpackButton.Visible = true
-
false
BackpackResizer
print("carrot is gay")
local t = {}
local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
local eventConnection = nil
--Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
local tryConnect = function()
if game:IsAncestorOf(parentInstance) then
--Entering the world, make sure we are connected/synced
if not eventConnection then
eventConnection = instance[event]:connect(signalFunc)
if syncFunc then syncFunc() end
end
else
--Probably leaving the world, so disconnect for now
if eventConnection then
eventConnection:disconnect()
if removeFunc then removeFunc() end
end
end
end
--Hook it up to ancestryChanged signal
local connection = parentInstance.AncestryChanged:connect(tryConnect)
--Now connect us if we're already in the world
tryConnect()
return connection
end
local function getScreenGuiAncestor(instance)
local localInstance = instance
while localInstance and not localInstance:IsA("ScreenGui") do
localInstance = localInstance.Parent
end
return localInstance
end
local function CreateButtons(frame, buttons, yPos, ySize)
local buttonNum = 1
local buttonObjs = {}
for i, obj in ipairs(buttons) do
local button = Instance.new("TextButton")
button.Name = "Button" .. buttonNum
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size18
button.AutoButtonColor = true
button.Modal = true
if obj["Style"] then
button.Style = obj.Style
else
button.Style = Enum.ButtonStyle.RobloxButton
end
if obj["ZIndex"] then
button.ZIndex = obj.ZIndex
end
button.Text = obj.Text
button.TextColor3 = Color3.new(1,1,1)
button.MouseButton1Click:connect(obj.Function)
button.Parent = frame
buttonObjs[buttonNum] = button
buttonNum = buttonNum + 1
end
local numButtons = buttonNum-1
if numButtons == 1 then
frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
elseif numButtons == 2 then
frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
elseif numButtons >= 3 then
local spacing = .1 / numButtons
local buttonSize = .9 / numButtons
buttonNum = 1
while buttonNum <= numButtons do
buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
buttonNum = buttonNum + 1
end
end
end
local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
local newStep = steps - 1 --otherwise we really get one more step than we want
local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
local wholeNum, remainder = math.modf(relativePosX * newStep)
if remainder > 0.5 then
wholeNum = wholeNum + 1
end
relativePosX = wholeNum/newStep
local result = math.ceil(relativePosX * newStep)
if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
sliderPosition.Value = result + 1
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end
end
local function cancelSlide(areaSoak)
areaSoak.Visible = false
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
end
t.CreateStyledMessageDialog = function(title, message, style, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0, 165)
frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local styleImage = Instance.new("ImageLabel")
styleImage.Name = "StyleImage"
styleImage.BackgroundTransparency = 1
styleImage.Position = UDim2.new(0,5,0,15)
if style == "error" or style == "Error" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42565285"
elseif style == "notify" or style == "Notify" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42604978"
elseif style == "confirm" or style == "Confirm" then
styleImage.Size = UDim2.new(0, 74, 0, 76)
styleImage.Image = "http://www.roblox.com/asset/?id=42557901"
else
return t.CreateMessageDialog(title,message,buttons)
end
styleImage.Parent = frame
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.TextStrokeTransparency = 0
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 80, 0, 0)
titleLabel.Size = UDim2.new(1, -80, 0, 40)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextStrokeTransparency = 0
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
return frame
end
t.CreateMessageDialog = function(title, message, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0.5, 0)
frame.Position = UDim2.new(0.25, 0, 0.25, 0)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 0, 0, 0)
titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
return frame
end
t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ)
local baseZIndex = 0
if (type(baseZ) == "number") then
baseZIndex = baseZ
end
local width = UDim.new(0, 100)
local height = UDim.new(0, 32)
local xPos = 0.055
local frame = Instance.new("Frame")
local textColor = Color3.new(1,1,1)
if (whiteSkin) then
textColor = Color3.new(0.5, 0.5, 0.5)
end
frame.Name = "DropDownMenu"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(width, height)
local dropDownMenu = Instance.new("TextButton")
dropDownMenu.Name = "DropDownMenuButton"
dropDownMenu.TextWrap = true
dropDownMenu.TextColor3 = textColor
dropDownMenu.Text = "Choose One"
dropDownMenu.Font = Enum.Font.ArialBold
dropDownMenu.FontSize = Enum.FontSize.Size18
dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
dropDownMenu.BackgroundTransparency = 1
dropDownMenu.AutoButtonColor = true
if (whiteSkin) then
dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
dropDownMenu.Size = UDim2.new(1,0,1,0)
dropDownMenu.Parent = frame
dropDownMenu.ZIndex = 2 + baseZIndex
local dropDownIcon = Instance.new("ImageLabel")
dropDownIcon.Name = "Icon"
dropDownIcon.Active = false
if (whiteSkin) then
dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png"
dropDownIcon.Size = UDim2.new(0,16,0,12)
dropDownIcon.Position = UDim2.new(1,-17,0.5, -6)
else
dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894"
dropDownIcon.Size = UDim2.new(0,11,0,6)
dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
end
dropDownIcon.BackgroundTransparency = 1
dropDownIcon.Parent = dropDownMenu
dropDownIcon.ZIndex = 2 + baseZIndex
local itemCount = #items
local dropDownItemCount = #items
local useScrollButtons = false
if dropDownItemCount > 6 then
useScrollButtons = true
dropDownItemCount = 6
end
local droppedDownMenu = Instance.new("TextButton")
droppedDownMenu.Name = "List"
droppedDownMenu.Text = ""
droppedDownMenu.BackgroundTransparency = 1
--droppedDownMenu.AutoButtonColor = true
if (whiteSkin) then
droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
droppedDownMenu.Visible = false
droppedDownMenu.Active = true --Blocks clicks
droppedDownMenu.Position = UDim2.new(0,0,0,0)
droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
droppedDownMenu.Parent = frame
droppedDownMenu.ZIndex = 2 + baseZIndex
local choiceButton = Instance.new("TextButton")
choiceButton.Name = "ChoiceButton"
choiceButton.BackgroundTransparency = 1
choiceButton.BorderSizePixel = 0
choiceButton.Text = "ReplaceMe"
choiceButton.TextColor3 = textColor
choiceButton.TextXAlignment = Enum.TextXAlignment.Left
choiceButton.TextYAlignment = Enum.TextYAlignment.Center
choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
choiceButton.Font = Enum.Font.Arial
choiceButton.FontSize = Enum.FontSize.Size18
if useScrollButtons then
choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
else
choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
end
choiceButton.TextWrap = true
choiceButton.ZIndex = 2 + baseZIndex
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = true
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 3 + baseZIndex
local dropDownSelected = false
local scrollUpButton
local scrollDownButton
local scrollMouseCount = 0
local setZIndex = function(baseZIndex)
droppedDownMenu.ZIndex = baseZIndex +1
if scrollUpButton then
scrollUpButton.ZIndex = baseZIndex + 3
end
if scrollDownButton then
scrollDownButton.ZIndex = baseZIndex + 3
end
local children = droppedDownMenu:GetChildren()
if children then
for i, child in ipairs(children) do
if child.Name == "ChoiceButton" then
child.ZIndex = baseZIndex + 2
elseif child.Name == "ClickCaptureButton" then
child.ZIndex = baseZIndex
end
end
end
end
local scrollBarPosition = 1
local updateScroll = function()
if scrollUpButton then
scrollUpButton.Active = scrollBarPosition > 1
end
if scrollDownButton then
scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
end
local children = droppedDownMenu:GetChildren()
if not children then return end
local childNum = 1
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
obj.Visible = false
else
obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
obj.Visible = true
end
obj.TextColor3 = textColor
obj.BackgroundTransparency = 1
childNum = childNum + 1
end
end
end
local toggleVisibility = function()
dropDownSelected = not dropDownSelected
areaSoak.Visible = not areaSoak.Visible
dropDownMenu.Visible = not dropDownSelected
droppedDownMenu.Visible = dropDownSelected
if dropDownSelected then
setZIndex(4 + baseZIndex)
else
setZIndex(2 + baseZIndex)
end
if useScrollButtons then
updateScroll()
end
end
droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
local updateSelection = function(text)
local foundItem = false
local children = droppedDownMenu:GetChildren()
local childNum = 1
if children then
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if obj.Text == text then
obj.Font = Enum.Font.ArialBold
foundItem = true
scrollBarPosition = childNum
if (whiteSkin) then
obj.TextColor3 = Color3.new(90/255,142/255,233/255)
end
else
obj.Font = Enum.Font.Arial
if (whiteSkin) then
obj.TextColor3 = textColor
end
end
childNum = childNum + 1
end
end
end
if not text then
dropDownMenu.Text = "Choose One"
scrollBarPosition = 1
else
if not foundItem then
error("Invalid Selection Update -- " .. text)
end
if scrollBarPosition + dropDownItemCount > itemCount + 1 then
scrollBarPosition = itemCount - dropDownItemCount + 1
end
dropDownMenu.Text = text
end
end
local function scrollDown()
if scrollBarPosition + dropDownItemCount <= itemCount then
scrollBarPosition = scrollBarPosition + 1
updateScroll()
return true
end
return false
end
local function scrollUp()
if scrollBarPosition > 1 then
scrollBarPosition = scrollBarPosition - 1
updateScroll()
return true
end
return false
end
if useScrollButtons then
--Make some scroll buttons
scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
scrollUpButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollUp()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollUp() == false then
break
end
wait(0.1)
end
end)
scrollUpButton.Parent = droppedDownMenu
scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
scrollDownButton.Position = UDim2.new(1,-11,1,-11)
scrollDownButton.Parent = droppedDownMenu
scrollDownButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollDown()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollDown() == false then
break
end
wait(0.1)
end
end)
local scrollbar = Instance.new("ImageLabel")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
scrollbar.Parent = droppedDownMenu
end
for i,item in ipairs(items) do
-- needed to maintain local scope for items in event listeners below
local button = choiceButton:clone()
if forRoblox then
button.RobloxLocked = true
end
button.Text = item
button.Parent = droppedDownMenu
if (whiteSkin) then
button.TextColor3 = textColor
end
button.MouseButton1Click:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
updateSelection(item)
onSelect(item)
toggleVisibility()
end)
button.MouseEnter:connect(function()
--Add Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(0,0,0)
end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
end)
end
--This does the initial layout of the buttons
updateScroll()
frame.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(frame)
end
end)
dropDownMenu.MouseButton1Click:connect(toggleVisibility)
areaSoak.MouseButton1Click:connect(toggleVisibility)
return frame, updateSelection
end
t.CreatePropertyDropDownMenu = function(instance, property, enum)
local items = enum:GetEnumItems()
local names = {}
local nameToItem = {}
for i,obj in ipairs(items) do
names[i] = obj.Name
nameToItem[obj.Name] = obj
end
local frame
local updateSelection
frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
ScopedConnect(frame, instance, "Changed",
function(prop)
if prop == property then
updateSelection(instance[property].Name)
end
end,
function()
updateSelection(instance[property].Name)
end)
return frame
end
t.GetFontHeight = function(font, fontSize)
if font == nil or fontSize == nil then
error("Font and FontSize must be non-nil")
end
if font == Enum.Font.Legacy then
if fontSize == Enum.FontSize.Size8 then
return 12
elseif fontSize == Enum.FontSize.Size9 then
return 14
elseif fontSize == Enum.FontSize.Size10 then
return 15
elseif fontSize == Enum.FontSize.Size11 then
return 17
elseif fontSize == Enum.FontSize.Size12 then
return 18
elseif fontSize == Enum.FontSize.Size14 then
return 21
elseif fontSize == Enum.FontSize.Size18 then
return 27
elseif fontSize == Enum.FontSize.Size24 then
return 36
elseif fontSize == Enum.FontSize.Size36 then
return 54
elseif fontSize == Enum.FontSize.Size48 then
return 72
else
error("Unknown FontSize")
end
elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
if fontSize == Enum.FontSize.Size8 then
return 8
elseif fontSize == Enum.FontSize.Size9 then
return 9
elseif fontSize == Enum.FontSize.Size10 then
return 10
elseif fontSize == Enum.FontSize.Size11 then
return 11
elseif fontSize == Enum.FontSize.Size12 then
return 12
elseif fontSize == Enum.FontSize.Size14 then
return 14
elseif fontSize == Enum.FontSize.Size18 then
return 18
elseif fontSize == Enum.FontSize.Size24 then
return 24
elseif fontSize == Enum.FontSize.Size36 then
return 36
elseif fontSize == Enum.FontSize.Size48 then
return 48
else
error("Unknown FontSize")
end
else
error("Unknown Font " .. font)
end
end
local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
for i, child in ipairs(guiObjects) do
if child:IsA("TextLabel") or child:IsA("TextButton") then
local isLabel = child:IsA("TextLabel")
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
if child.TextFits and child.TextBounds.Y < pixelsRemaining then
child.Visible = true
if isLabel then
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
else
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
end
while not child.TextFits do
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
end
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
else
child.Visible = false
pixelsRemaining = -1
end
else
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
child.Visible = (pixelsRemaining >= 0)
end
end
end
t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
if not frame:IsA("GuiObject") then
error("Frame must be a GuiObject")
end
for i, child in ipairs(guiObjects) do
if not child:IsA("GuiObject") then
error("All elements that are layed out must be of type GuiObject")
end
end
if not settingsTable then
settingsTable = {}
end
if not settingsTable["TextLabelSizePadY"] then
settingsTable["TextLabelSizePadY"] = 0
end
if not settingsTable["TextLabelPositionPadY"] then
settingsTable["TextLabelPositionPadY"] = 0
end
if not settingsTable["TextButtonSizePadY"] then
settingsTable["TextButtonSizePadY"] = 12
end
if not settingsTable["TextButtonPositionPadY"] then
settingsTable["TextButtonPositionPadY"] = 2
end
--Wrapper frame takes care of styled objects
local wrapperFrame = Instance.new("Frame")
wrapperFrame.Name = "WrapperFrame"
wrapperFrame.BackgroundTransparency = 1
wrapperFrame.Size = UDim2.new(1,0,1,0)
wrapperFrame.Parent = frame
for i, child in ipairs(guiObjects) do
child.Parent = wrapperFrame
end
local recalculate = function()
wait()
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(recalculate)
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
t.CreateSlider = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 4
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local bar = Instance.new("TextButton")
bar.Text = ""
bar.AutoButtonColor = false
bar.Name = "Bar"
bar.BackgroundColor3 = Color3.new(0,0,0)
if type(width) == "number" then
bar.Size = UDim2.new(0,width,0,5)
else
bar.Size = UDim2.new(0,200,0,5)
end
bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
bar.ZIndex = 2
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/Slider.png"
slider.Position = UDim2.new(0,0,0.5,-10)
slider.Size = UDim2.new(0,20,0,20)
slider.ZIndex = 3
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateSliderNew = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 6
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local sliderBarImgHeight = 7
local sliderBarCapImgWidth = 4
local bar = Instance.new("ImageButton")
bar.BackgroundTransparency = 1
bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png"
bar.Name = "Bar"
local displayWidth = 200
if type(width) == "number" then
bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight)
displayWidth = width - (sliderBarCapImgWidth * 2)
else
bar.Size = UDim2.new(0,200,0,sliderBarImgHeight)
end
bar.ZIndex = 3
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local barLeft = bar:clone()
barLeft.Name = "BarLeft"
barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png"
barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight)
barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset)
barLeft.Parent = sliderGui
barLeft.ZIndex = 3
local barRight = barLeft:clone()
barRight.Name = "BarRight"
barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png"
barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset)
barRight.Parent = sliderGui
local fillLeft = barLeft:clone()
fillLeft.Name = "FillLeft"
fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png"
fillLeft.Parent = sliderGui
fillLeft.ZIndex = 4
local fill = fillLeft:clone()
fill.Name = "Fill"
fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png"
fill.Parent = bar
fill.ZIndex = 4
fill.Position = UDim2.new(0, 0, 0, 0)
fill.Size = UDim2.new(0.5, 0, 1, 0)
-- bar.Visible = false
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/slider_new_tab.png"
slider.Position = UDim2.new(0,0,0.5,-14)
slider.Size = UDim2.new(0,28,0,28)
slider.ZIndex = 5
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
fill.Size = UDim2.new(relativePosX, 0, 1, 0)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateTrueScrollingFrame = function()
local lowY = nil
local highY = nil
local dragCon = nil
local upCon = nil
local internalChange = false
local descendantsChangeConMap = {}
local scrollingFrame = Instance.new("Frame")
scrollingFrame.Name = "ScrollingFrame"
scrollingFrame.Active = true
scrollingFrame.Size = UDim2.new(1,0,1,0)
scrollingFrame.ClipsDescendants = true
local controlFrame = Instance.new("Frame")
controlFrame.Name = "ControlFrame"
controlFrame.BackgroundTransparency = 1
controlFrame.Size = UDim2.new(0,18,1,0)
controlFrame.Position = UDim2.new(1,-20,0,0)
controlFrame.Parent = scrollingFrame
local scrollBottom = Instance.new("BoolValue")
scrollBottom.Value = false
scrollBottom.Name = "ScrollBottom"
scrollBottom.Parent = controlFrame
local scrollUp = Instance.new("BoolValue")
scrollUp.Value = false
scrollUp.Name = "scrollUp"
scrollUp.Parent = controlFrame
local scrollUpButton = Instance.new("TextButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.Text = ""
scrollUpButton.AutoButtonColor = false
scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
scrollUpButton.BorderColor3 = Color3.new(1,1,1)
scrollUpButton.BackgroundTransparency = 0.5
scrollUpButton.Size = UDim2.new(0,18,0,18)
scrollUpButton.ZIndex = 2
scrollUpButton.Parent = controlFrame
for i = 1, 6 do
local triFrame = Instance.new("Frame")
triFrame.BorderColor3 = Color3.new(1,1,1)
triFrame.Name = "tri" .. tostring(i)
triFrame.ZIndex = 3
triFrame.BackgroundTransparency = 0.5
triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
triFrame.Parent = scrollUpButton
end
scrollUpButton.MouseEnter:connect(function()
scrollUpButton.BackgroundTransparency = 0.1
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.1
end
end)
scrollUpButton.MouseLeave:connect(function()
scrollUpButton.BackgroundTransparency = 0.5
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.5
end
end)
local scrollDownButton = scrollUpButton:clone()
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.Position = UDim2.new(0,0,1,-18)
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
end
scrollDownButton.MouseEnter:connect(function()
scrollDownButton.BackgroundTransparency = 0.1
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.1
end
end)
scrollDownButton.MouseLeave:connect(function()
scrollDownButton.BackgroundTransparency = 0.5
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.5
end
end)
scrollDownButton.Parent = controlFrame
local scrollTrack = Instance.new("Frame")
scrollTrack.Name = "ScrollTrack"
scrollTrack.BackgroundTransparency = 1
scrollTrack.Size = UDim2.new(0,18,1,-38)
scrollTrack.Position = UDim2.new(0,0,0,19)
scrollTrack.Parent = controlFrame
local scrollbar = Instance.new("TextButton")
scrollbar.BackgroundColor3 = Color3.new(0,0,0)
scrollbar.BorderColor3 = Color3.new(1,1,1)
scrollbar.BackgroundTransparency = 0.5
scrollbar.AutoButtonColor = false
scrollbar.Text = ""
scrollbar.Active = true
scrollbar.Name = "ScrollBar"
scrollbar.ZIndex = 2
scrollbar.BackgroundTransparency = 0.5
scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
scrollbar.Position = UDim2.new(0,0,0,0)
scrollbar.Parent = scrollTrack
local scrollNub = Instance.new("Frame")
scrollNub.Name = "ScrollNub"
scrollNub.BorderColor3 = Color3.new(1,1,1)
scrollNub.Size = UDim2.new(0,10,0,0)
scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
scrollNub.ZIndex = 2
scrollNub.BackgroundTransparency = 0.5
scrollNub.Parent = scrollbar
local newNub = scrollNub:clone()
newNub.Position = UDim2.new(0.5,-5,0.5,-2)
newNub.Parent = scrollbar
local lastNub = scrollNub:clone()
lastNub.Position = UDim2.new(0.5,-5,0.5,2)
lastNub.Parent = scrollbar
scrollbar.MouseEnter:connect(function()
scrollbar.BackgroundTransparency = 0.1
scrollNub.BackgroundTransparency = 0.1
newNub.BackgroundTransparency = 0.1
lastNub.BackgroundTransparency = 0.1
end)
scrollbar.MouseLeave:connect(function()
scrollbar.BackgroundTransparency = 0.5
scrollNub.BackgroundTransparency = 0.5
newNub.BackgroundTransparency = 0.5
lastNub.BackgroundTransparency = 0.5
end)
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local function positionScrollBar(x,y,offset)
local oldPos = scrollbar.Position
if y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
return (oldPos ~= scrollbar.Position)
end
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
return (oldPos ~= scrollbar.Position)
end
local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
if newScaleYPos + relativeSize > 1 then
newScaleYPos = 1 - relativeSize
scrollBottom.Value = true
scrollUp.Value = false
elseif newScaleYPos <= 0 then
newScaleYPos = 0
scrollUp.Value = true
scrollBottom.Value = false
else
scrollUp.Value = false
scrollBottom.Value = false
end
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
return (oldPos ~= scrollbar.Position)
end
local function drillDownSetHighLow(instance)
if not instance or not instance:IsA("GuiObject") then return end
if instance == controlFrame then return end
if instance:IsDescendantOf(controlFrame) then return end
if not instance.Visible then return end
if lowY and lowY > instance.AbsolutePosition.Y then
lowY = instance.AbsolutePosition.Y
elseif not lowY then
lowY = instance.AbsolutePosition.Y
end
if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
local children = instance:GetChildren()
for i = 1, #children do
drillDownSetHighLow(children[i])
end
end
local function resetHighLow()
local firstChildren = scrollingFrame:GetChildren()
for i = 1, #firstChildren do
drillDownSetHighLow(firstChildren[i])
end
end
local function recalculate()
internalChange = true
local percentFrame = 0
if scrollbar.Position.Y.Scale > 0 then
if scrollbar.Visible then
percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
else
percentFrame = 0
end
end
if percentFrame > 0.99 then percentFrame = 1 end
local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
local guiChildren = scrollingFrame:GetChildren()
for i = 1, #guiChildren do
if guiChildren[i] ~= controlFrame then
guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
end
end
lowY = nil
highY = nil
resetHighLow()
internalChange = false
end
local function setSliderSizeAndPosition()
if not highY or not lowY then return end
local totalYSpan = math.abs(highY - lowY)
if totalYSpan == 0 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
return
end
local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
if percentShown >= 1 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
recalculate()
else
scrollbar.Visible = true
scrollDownButton.Visible = true
scrollUpButton.Visible = true
scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
end
local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
end
if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
end
end
local buttonScrollAmountPixels = 7
local reentrancyGuardScrollUp = false
local function doScrollUp()
if reentrancyGuardScrollUp then return end
reentrancyGuardScrollUp = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollUp = false
end
local reentrancyGuardScrollDown = false
local function doScrollDown()
if reentrancyGuardScrollDown then return end
reentrancyGuardScrollDown = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollDown = false
end
local function scrollUp(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local function scrollDown(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
scrollbar.MouseButton1Down:connect(function(x,y)
if scrollbar.Active then
scrollStamp = tick()
local mouseOffset = y - scrollbar.AbsolutePosition.y
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
local prevY = y
local reentrancyGuardMouseScroll = false
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
if reentrancyGuardMouseScroll then return end
reentrancyGuardMouseScroll = true
if positionScrollBar(x,y,mouseOffset) then
recalculate()
end
reentrancyGuardMouseScroll = false
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
local function heightCheck(instance)
if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
setSliderSizeAndPosition()
end
local function highLowRecheck()
local oldLowY = lowY
local oldHighY = highY
lowY = nil
highY = nil
resetHighLow()
if (lowY ~= oldLowY) or (highY ~= oldHighY) then
setSliderSizeAndPosition()
end
end
local function descendantChanged(this, prop)
if internalChange then return end
if not this.Visible then return end
if prop == "Size" or prop == "Position" then
wait()
highLowRecheck()
end
end
scrollingFrame.DescendantAdded:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if instance.Visible then
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end
descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
end)
scrollingFrame.DescendantRemoving:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if descendantsChangeConMap[instance] then
descendantsChangeConMap[instance]:disconnect()
descendantsChangeConMap[instance] = nil
end
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end)
scrollingFrame.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if not highY or not lowY then return end
highLowRecheck()
setSliderSizeAndPosition()
end
end)
return scrollingFrame, controlFrame
end
t.CreateScrollingFrame = function(orderList,scrollStyle)
local frame = Instance.new("Frame")
frame.Name = "ScrollingFrame"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1,0,1,0)
local scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
local scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
local scrollbar = Instance.new("ImageButton")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, 0, 150)
local scrollStamp = 0
local scrollDrag = Instance.new("ImageButton")
scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186"
scrollDrag.Size = UDim2.new(1, 0, 0, 16)
scrollDrag.BackgroundTransparency = 1
scrollDrag.Name = "ScrollDrag"
scrollDrag.Active = true
scrollDrag.Parent = scrollbar
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local style = "simple"
if scrollStyle and tostring(scrollStyle) then
style = scrollStyle
end
local scrollPosition = 1
local rowSize = 0
local howManyDisplayed = 0
local layoutGridScrollBar = function()
howManyDisplayed = 0
local guiObjects = {}
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
if scrollPosition < 1 then scrollPosition = 1 end
local totalPixelsY = frame.AbsoluteSize.Y
local pixelsRemainingY = frame.AbsoluteSize.Y
local totalPixelsX = frame.AbsoluteSize.X
local xCounter = 0
local rowSizeCounter = 0
local setRowSize = true
local pixelsBelowScrollbar = 0
local pos = #guiObjects
local currentRowY = 0
pos = scrollPosition
--count up from current scroll position to fill out grid
while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
--previous pos was the end of a row
if xCounter >= totalPixelsX then
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
xCounter = guiObjects[pos].AbsoluteSize.X
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos + 1
end
--Count wherever current row left off
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
pos = scrollPosition - 1
xCounter = 0
--objects with varying X,Y dimensions can rarely cause minor errors
--rechecking every new scrollPosition is necessary to avoid 100% of errors
--count backwards from current scrollPosition to see if we can add more rows
while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
rowSizeCounter = rowSizeCounter + 1
if xCounter >= totalPixelsX then
rowSize = rowSizeCounter - 1
rowSizeCounter = 0
xCounter = guiObjects[pos].AbsoluteSize.X
if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
if scrollPosition <= rowSize then
scrollPosition = 1
break
else
scrollPosition = scrollPosition - rowSize
end
currentRowY = 0
else
break
end
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos - 1
end
--Do check last time if pos = 0
if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
scrollPosition = 1
end
xCounter = 0
--pos = scrollPosition
rowSizeCounter = 0
setRowSize = true
local lastChildSize = 0
local xOffset,yOffset = 0
if guiObjects[1] then
yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
end
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemainingY < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
if xCounter + child.AbsoluteSize.X >= totalPixelsX then
if setRowSize then
rowSize = rowSizeCounter - 1
setRowSize = false
end
xCounter = 0
pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
end
child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
xCounter = xCounter + child.AbsoluteSize.X
child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
if child.Visible then
howManyDisplayed = howManyDisplayed + 1
end
lastChildSize = child.AbsoluteSize
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
if lastChildSize == 0 then
scrollDownButton.Active = false
else
scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
end
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local layoutSimpleScrollBar = function()
local guiObjects = {}
howManyDisplayed = 0
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
local pixelsBelowScrollbar = 0
local pos = #guiObjects
while pixelsBelowScrollbar < totalPixels and pos >= 1 do
if pos >= scrollPosition then
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
else
if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
if scrollPosition <= 1 then
scrollPosition = 1
break
else
--local ("Backing up ScrollPosition from -- " ..scrollPosition)
scrollPosition = scrollPosition - 1
end
else
break
end
end
pos = pos - 1
end
pos = scrollPosition
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemaining < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if (pixelsRemaining >= 0) then
child.Visible = true
howManyDisplayed = howManyDisplayed + 1
else
child.Visible = false
end
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
scrollDownButton.Active = (pixelsRemaining < 0)
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local moveDragger = function()
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
if not scrollDrag.Parent then return end
local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
if dragSizeY < 16 then dragSizeY = 16 end
scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
if relativeYPos > 1 then relativeYPos = 1
elseif relativeYPos < 0 then relativeYPos = 0 end
local absYPos = 0
if relativeYPos ~= 0 then
absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
end
scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
end
local reentrancyGuard = false
local recalculate = function()
if reentrancyGuard then
return
end
reentrancyGuard = true
wait()
local success, err = nil
if style == "grid" then
success, err = pcall(function() layoutGridScrollBar() end)
elseif style == "simple" then
success, err = pcall(function() layoutSimpleScrollBar() end)
end
if not success then print(err) end
moveDragger()
reentrancyGuard = false
end
local doScrollUp = function()
scrollPosition = (scrollPosition) - rowSize
if scrollPosition < 1 then scrollPosition = 1 end
recalculate(nil)
end
local doScrollDown = function()
scrollPosition = (scrollPosition) + rowSize
recalculate(nil)
end
local scrollUp = function(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local scrollDown = function(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local y = 0
scrollDrag.MouseButton1Down:connect(function(x,y)
if scrollDrag.Active then
scrollStamp = tick()
local mouseOffset = y - scrollDrag.AbsolutePosition.y
local dragCon
local upCon
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
local barAbsPos = scrollbar.AbsolutePosition.y
local barAbsSize = scrollbar.AbsoluteSize.y
local dragAbsSize = scrollDrag.AbsoluteSize.y
local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
y = y - mouseOffset
y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
y = y - barAbsPos
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
local doublePercent = y/(barAbsSize-dragAbsSize)
local rowDiff = rowSize
local totalScrollCount = guiObjects - (howManyDisplayed - 1)
local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
if newScrollPosition < scrollPosition then
rowDiff = -rowDiff
end
if newScrollPosition < 1 then
newScrollPosition = 1
end
scrollPosition = newScrollPosition
recalculate(nil)
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(
function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollbar.MouseButton1Down:connect(
function(x,y)
if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
scrollDown(y)
elseif y < (scrollDrag.AbsolutePosition.y) then
scrollUp(y)
end
end)
frame.ChildAdded:connect(function()
recalculate(nil)
end)
frame.ChildRemoved:connect(function()
recalculate(nil)
end)
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(function() recalculate(nil) end)
return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
end
local function binaryGrow(min, max, fits)
if min > max then
return min
end
local biggestLegal = min
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
biggestLegal = mid
--Try growing
min = mid + 1
else
--Doesn't fit, shrink
max = mid - 1
end
end
return biggestLegal
end
local function binaryShrink(min, max, fits)
if min > max then
return min
end
local smallestLegal = max
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
smallestLegal = mid
--It fits, shrink
max = mid - 1
else
--Doesn't fit, grow
min = mid + 1
end
end
return smallestLegal
end
local function getGuiOwner(instance)
while instance ~= nil do
if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
return instance
end
instance = instance.Parent
end
return nil
end
t.AutoTruncateTextObject = function(textLabel)
local text = textLabel.Text
local fullLabel = textLabel:Clone()
fullLabel.Name = "Full" .. textLabel.Name
fullLabel.BorderSizePixel = 0
fullLabel.BackgroundTransparency = 0
fullLabel.Text = text
fullLabel.TextXAlignment = Enum.TextXAlignment.Center
fullLabel.Position = UDim2.new(0,-3,0,0)
fullLabel.Size = UDim2.new(0,100,1,0)
fullLabel.Visible = false
fullLabel.Parent = textLabel
local shortText = nil
local mouseEnterConnection = nil
local mouseLeaveConnection= nil
local checkForResize = function()
if getGuiOwner(textLabel) == nil then
return
end
textLabel.Text = text
if textLabel.TextFits then
--Tear down the rollover if it is active
if mouseEnterConnection then
mouseEnterConnection:disconnect()
mouseEnterConnection = nil
end
if mouseLeaveConnection then
mouseLeaveConnection:disconnect()
mouseLeaveConnection = nil
end
else
local len = string.len(text)
textLabel.Text = text .. "~"
--Shrink the text
local textSize = binaryGrow(0, len,
function(pos)
if pos == 0 then
textLabel.Text = "~"
else
textLabel.Text = string.sub(text, 1, pos) .. "~"
end
return textLabel.TextFits
end)
shortText = string.sub(text, 1, textSize) .. "~"
textLabel.Text = shortText
--Make sure the fullLabel fits
if not fullLabel.TextFits then
--Already too small, grow it really bit to start
fullLabel.Size = UDim2.new(0, 10000, 1, 0)
end
--Okay, now try to binary shrink it back down
local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
function(size)
fullLabel.Size = UDim2.new(0, size, 1, 0)
return fullLabel.TextFits
end)
fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
--Now setup the rollover effects, if they are currently off
if mouseEnterConnection == nil then
mouseEnterConnection = textLabel.MouseEnter:connect(
function()
fullLabel.ZIndex = textLabel.ZIndex + 1
fullLabel.Visible = true
--textLabel.Text = ""
end)
end
if mouseLeaveConnection == nil then
mouseLeaveConnection = textLabel.MouseLeave:connect(
function()
fullLabel.Visible = false
--textLabel.Text = shortText
end)
end
end
end
textLabel.AncestryChanged:connect(checkForResize)
textLabel.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
checkForResize()
end
end)
checkForResize()
local function changeText(newText)
text = newText
fullLabel.Text = text
checkForResize()
end
return textLabel, changeText
end
local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
if fromPage then
fromPage.Visible = false
if transitionFrame.Visible == false then
transitionFrame.Size = fromPage.Size
transitionFrame.Position = fromPage.Position
end
else
if transitionFrame.Visible == false then
transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
end
end
transitionFrame.Visible = true
currentPageValue.Value = nil
local newsize, newPosition
if toPage then
--Make it visible so it resizes
toPage.Visible = true
newSize = toPage.Size
newPosition = toPage.Position
toPage.Visible = false
else
newSize = UDim2.new(0.0,50,0.0,50)
newPosition = UDim2.new(0.5,-25,0.5,-25)
end
transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
function(state)
if state == Enum.TweenStatus.Completed then
transitionFrame.Visible = false
if toPage then
toPage.Visible = true
currentPageValue.Value = toPage
end
end
end)
end
t.CreateTutorial = function(name, tutorialKey, createButtons)
local frame = Instance.new("Frame")
frame.Name = "Tutorial-" .. name
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
local transitionFrame = Instance.new("Frame")
transitionFrame.Name = "TransitionFrame"
transitionFrame.Style = Enum.FrameStyle.RobloxRound
transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
transitionFrame.Visible = false
transitionFrame.Parent = frame
local currentPageValue = Instance.new("ObjectValue")
currentPageValue.Name = "CurrentTutorialPage"
currentPageValue.Value = nil
currentPageValue.Parent = frame
local boolValue = Instance.new("BoolValue")
boolValue.Name = "Buttons"
boolValue.Value = createButtons
boolValue.Parent = frame
local pages = Instance.new("Frame")
pages.Name = "Pages"
pages.BackgroundTransparency = 1
pages.Size = UDim2.new(1,0,1,0)
pages.Parent = frame
local function getVisiblePageAndHideOthers()
local visiblePage = nil
local children = pages:GetChildren()
if children then
for i,child in ipairs(children) do
if child.Visible then
if visiblePage then
child.Visible = false
else
visiblePage = child
end
end
end
end
return visiblePage
end
local showTutorial = function(alwaysShow)
if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
print("Showing tutorial-",tutorialKey)
local currentTutorialPage = getVisiblePageAndHideOthers()
local firstPage = pages:FindFirstChild("TutorialPage1")
if firstPage then
TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
else
error("Could not find TutorialPage1")
end
end
end
local dismissTutorial = function()
local currentTutorialPage = getVisiblePageAndHideOthers()
if currentTutorialPage then
TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
end
UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
end
local gotoPage = function(pageNum)
local page = pages:FindFirstChild("TutorialPage" .. pageNum)
local currentTutorialPage = getVisiblePageAndHideOthers()
TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
end
return frame, showTutorial, dismissTutorial, gotoPage
end
local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
local frame = Instance.new("Frame")
frame.Name = "TutorialPage"
frame.Style = Enum.FrameStyle.RobloxRound
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
frame.Visible = false
local frameHeader = Instance.new("TextLabel")
frameHeader.Name = "Header"
frameHeader.Text = name
frameHeader.BackgroundTransparency = 1
frameHeader.FontSize = Enum.FontSize.Size24
frameHeader.Font = Enum.Font.ArialBold
frameHeader.TextColor3 = Color3.new(1,1,1)
frameHeader.TextXAlignment = Enum.TextXAlignment.Center
frameHeader.TextWrap = true
frameHeader.Size = UDim2.new(1,-55, 0, 22)
frameHeader.Position = UDim2.new(0,0,0,0)
frameHeader.Parent = frame
local skipButton = Instance.new("ImageButton")
skipButton.Name = "SkipButton"
skipButton.AutoButtonColor = false
skipButton.BackgroundTransparency = 1
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
skipButton.MouseButton1Click:connect(function()
skipTutorial()
end)
skipButton.MouseEnter:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
end)
skipButton.MouseLeave:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
end)
skipButton.Size = UDim2.new(0, 25, 0, 25)
skipButton.Position = UDim2.new(1, -25, 0, 0)
skipButton.Parent = frame
if giveDoneButton then
local doneButton = Instance.new("TextButton")
doneButton.Name = "DoneButton"
doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
doneButton.Text = "Done"
doneButton.TextColor3 = Color3.new(1,1,1)
doneButton.Font = Enum.Font.ArialBold
doneButton.FontSize = Enum.FontSize.Size18
doneButton.Size = UDim2.new(0,100,0,50)
doneButton.Position = UDim2.new(0.5,-50,1,-50)
if skipTutorial then
doneButton.MouseButton1Click:connect(function() skipTutorial() end)
end
doneButton.Parent = frame
end
local innerFrame = Instance.new("Frame")
innerFrame.Name = "ContentFrame"
innerFrame.BackgroundTransparency = 1
innerFrame.Position = UDim2.new(0,0,0,25)
innerFrame.Parent = frame
local nextButton = Instance.new("TextButton")
nextButton.Name = "NextButton"
nextButton.Text = "Next"
nextButton.TextColor3 = Color3.new(1,1,1)
nextButton.Font = Enum.Font.Arial
nextButton.FontSize = Enum.FontSize.Size18
nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
nextButton.Size = UDim2.new(0,80, 0, 32)
nextButton.Position = UDim2.new(0.5, 5, 1, -32)
nextButton.Active = false
nextButton.Visible = false
nextButton.Parent = frame
local prevButton = Instance.new("TextButton")
prevButton.Name = "PrevButton"
prevButton.Text = "Previous"
prevButton.TextColor3 = Color3.new(1,1,1)
prevButton.Font = Enum.Font.Arial
prevButton.FontSize = Enum.FontSize.Size18
prevButton.Style = Enum.ButtonStyle.RobloxButton
prevButton.Size = UDim2.new(0,80, 0, 32)
prevButton.Position = UDim2.new(0.5, -85, 1, -32)
prevButton.Active = false
prevButton.Visible = false
prevButton.Parent = frame
if giveDoneButton then
innerFrame.Size = UDim2.new(1,0,1,-75)
else
innerFrame.Size = UDim2.new(1,0,1,-22)
end
local parentConnection = nil
local function basicHandleResize()
if frame.Visible and frame.Parent then
local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
handleResize(200,maxSize)
end
end
frame.Changed:connect(
function(prop)
if prop == "Parent" then
if parentConnection ~= nil then
parentConnection:disconnect()
parentConnection = nil
end
if frame.Parent and frame.Parent:IsA("GuiObject") then
parentConnection = frame.Parent.Changed:connect(
function(parentProp)
if parentProp == "AbsoluteSize" then
wait()
basicHandleResize()
end
end)
basicHandleResize()
end
end
if prop == "Visible" then
basicHandleResize()
end
end)
return frame, innerFrame
end
t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
local frame = nil
local contentFrame = nil
local textLabel = Instance.new("TextLabel")
textLabel.BackgroundTransparency = 1
textLabel.TextColor3 = Color3.new(1,1,1)
textLabel.Text = text
textLabel.TextWrap = true
textLabel.TextXAlignment = Enum.TextXAlignment.Left
textLabel.TextYAlignment = Enum.TextYAlignment.Center
textLabel.Font = Enum.Font.Arial
textLabel.FontSize = Enum.FontSize.Size14
textLabel.Size = UDim2.new(1,0,1,0)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
frame.Size = UDim2.new(0, size, 0, size)
return textLabel.TextFits
end)
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
textLabel.Parent = contentFrame
return frame
end
t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
local frame = nil
local contentFrame = nil
local imageLabel = Instance.new("ImageLabel")
imageLabel.BackgroundTransparency = 1
imageLabel.Image = imageAsset
imageLabel.Size = UDim2.new(0,x,0,y)
imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
return size >= x and size >= y
end)
if size >= x and size >= y then
imageLabel.Size = UDim2.new(0,x, 0,y)
imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
else
if x > y then
--X is limiter, so
imageLabel.Size = UDim2.new(1,0,y/x,0)
imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
else
--Y is limiter
imageLabel.Size = UDim2.new(x/y,0,1, 0)
imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
end
end
size = size + 50
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
imageLabel.Parent = contentFrame
return frame
end
t.AddTutorialPage = function(tutorial, tutorialPage)
local transitionFrame = tutorial.TransitionFrame
local currentPageValue = tutorial.CurrentTutorialPage
if not tutorial.Buttons.Value then
tutorialPage.NextButton.Parent = nil
tutorialPage.PrevButton.Parent = nil
end
local children = tutorial.Pages:GetChildren()
if children and #children > 0 then
tutorialPage.Name = "TutorialPage" .. (#children+1)
local previousPage = children[#children]
if not previousPage:IsA("GuiObject") then
error("All elements under Pages must be GuiObjects")
end
if tutorial.Buttons.Value then
if previousPage.NextButton.Active then
error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
end
previousPage.NextButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
end)
previousPage.NextButton.Active = true
previousPage.NextButton.Visible = true
if tutorialPage.PrevButton.Active then
error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
end
tutorialPage.PrevButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
end)
tutorialPage.PrevButton.Active = true
tutorialPage.PrevButton.Visible = true
end
tutorialPage.Parent = tutorial.Pages
else
--First child
tutorialPage.Name = "TutorialPage1"
tutorialPage.Parent = tutorial.Pages
end
end
t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
if not userIdsForSets then
error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
end
if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
end
if not objectSelected then
error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
end
if type(objectSelected) ~= "function" then
error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
end
if dialogClosed and type(dialogClosed) ~= "function" then
error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
end
if showAdminCategories == nil then -- by default, don't show beta sets
showAdminCategories = false
end
local arrayPosition = 1
local insertButtons = {}
local insertButtonCons = {}
local contents = nil
local setGui = nil
-- used for water selections
local waterForceDirection = "NegX"
local waterForce = "None"
local waterGui, waterTypeChangedEvent = nil
local Data = {}
Data.CurrentCategory = nil
Data.Category = {}
local SetCache = {}
local userCategoryButtons = nil
local buttonWidth = 64
local buttonHeight = buttonWidth
local SmallThumbnailUrl = nil
local LargeThumbnailUrl = nil
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if useAssetVersionId then
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
else
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
end
local function drillDownSetZIndex(parent, index)
local children = parent:GetChildren()
for i = 1, #children do
if children[i]:IsA("GuiObject") then
children[i].ZIndex = index
end
drillDownSetZIndex(children[i], index)
end
end
-- for terrain stamping
local currTerrainDropDownFrame = nil
local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
local terrainShapeMap = {}
for i = 1, #terrainShapes do
terrainShapeMap[terrainShapes[i]] = i - 1
end
terrainShapeMap[terrainShapes[#terrainShapes]] = 6
local function createWaterGui()
local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
local waterFrame = Instance.new("Frame")
waterFrame.Name = "WaterFrame"
waterFrame.Style = Enum.FrameStyle.RobloxSquare
waterFrame.Size = UDim2.new(0,150,0,110)
waterFrame.Visible = false
local waterForceLabel = Instance.new("TextLabel")
waterForceLabel.Name = "WaterForceLabel"
waterForceLabel.BackgroundTransparency = 1
waterForceLabel.Size = UDim2.new(1,0,0,12)
waterForceLabel.Font = Enum.Font.ArialBold
waterForceLabel.FontSize = Enum.FontSize.Size12
waterForceLabel.TextColor3 = Color3.new(1,1,1)
waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
waterForceLabel.Text = "Water Force"
waterForceLabel.Parent = waterFrame
local waterForceDirLabel = waterForceLabel:Clone()
waterForceDirLabel.Name = "WaterForceDirectionLabel"
waterForceDirLabel.Text = "Water Force Direction"
waterForceDirLabel.Position = UDim2.new(0,0,0,50)
waterForceDirLabel.Parent = waterFrame
local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
local waterForceDirectionSelectedFunc = function(newForceDirection)
waterForceDirection = newForceDirection
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceSelectedFunc = function(newForce)
waterForce = newForce
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
forceWaterDirectionSelection("NegX")
waterForceDirectionDropDown.Parent = waterForceDirLabel
local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
forceWaterForceSelection("None")
waterForceDropDown.Size = UDim2.new(1,0,0,25)
waterForceDropDown.Position = UDim2.new(0,0,1,3)
waterForceDropDown.Parent = waterForceLabel
return waterFrame, waterTypeChangedEvent
end
-- Helper Function that contructs gui elements
local function createSetGui()
local setGui = Instance.new("ScreenGui")
setGui.Name = "SetGui"
local setPanel = Instance.new("Frame")
setPanel.Name = "SetPanel"
setPanel.Active = true
setPanel.BackgroundTransparency = 1
if position then
setPanel.Position = position
else
setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
end
if size then
setPanel.Size = size
else
setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
end
setPanel.Style = Enum.FrameStyle.RobloxRound
setPanel.ZIndex = 6
setPanel.Parent = setGui
-- Children of SetPanel
local itemPreview = Instance.new("Frame")
itemPreview.Name = "ItemPreview"
itemPreview.BackgroundTransparency = 1
itemPreview.Position = UDim2.new(0.8,5,0.085,0)
itemPreview.Size = UDim2.new(0.21,0,0.9,0)
itemPreview.ZIndex = 6
itemPreview.Parent = setPanel
-- Children of ItemPreview
local textPanel = Instance.new("Frame")
textPanel.Name = "TextPanel"
textPanel.BackgroundTransparency = 1
textPanel.Position = UDim2.new(0,0,0.45,0)
textPanel.Size = UDim2.new(1,0,0.55,0)
textPanel.ZIndex = 6
textPanel.Parent = itemPreview
-- Children of TextPanel
local rolloverText = Instance.new("TextLabel")
rolloverText.Name = "RolloverText"
rolloverText.BackgroundTransparency = 1
rolloverText.Size = UDim2.new(1,0,0,48)
rolloverText.ZIndex = 6
rolloverText.Font = Enum.Font.ArialBold
rolloverText.FontSize = Enum.FontSize.Size24
rolloverText.Text = ""
rolloverText.TextColor3 = Color3.new(1,1,1)
rolloverText.TextWrap = true
rolloverText.TextXAlignment = Enum.TextXAlignment.Left
rolloverText.TextYAlignment = Enum.TextYAlignment.Top
rolloverText.Parent = textPanel
local largePreview = Instance.new("ImageLabel")
largePreview.Name = "LargePreview"
largePreview.BackgroundTransparency = 1
largePreview.Image = ""
largePreview.Size = UDim2.new(1,0,0,170)
largePreview.ZIndex = 6
largePreview.Parent = itemPreview
local sets = Instance.new("Frame")
sets.Name = "Sets"
sets.BackgroundTransparency = 1
sets.Position = UDim2.new(0,0,0,5)
sets.Size = UDim2.new(0.23,0,1,-5)
sets.ZIndex = 6
sets.Parent = setPanel
-- Children of Sets
local line = Instance.new("Frame")
line.Name = "Line"
line.BackgroundColor3 = Color3.new(1,1,1)
line.BackgroundTransparency = 0.7
line.BorderSizePixel = 0
line.Position = UDim2.new(1,-3,0.06,0)
line.Size = UDim2.new(0,3,0.9,0)
line.ZIndex = 6
line.Parent = sets
local setsLists, controlFrame = t.CreateTrueScrollingFrame()
setsLists.Size = UDim2.new(1,-6,0.94,0)
setsLists.Position = UDim2.new(0,0,0.06,0)
setsLists.BackgroundTransparency = 1
setsLists.Name = "SetsLists"
setsLists.ZIndex = 6
setsLists.Parent = sets
drillDownSetZIndex(controlFrame, 7)
local setsHeader = Instance.new("TextLabel")
setsHeader.Name = "SetsHeader"
setsHeader.BackgroundTransparency = 1
setsHeader.Size = UDim2.new(0,47,0,24)
setsHeader.ZIndex = 6
setsHeader.Font = Enum.Font.ArialBold
setsHeader.FontSize = Enum.FontSize.Size24
setsHeader.Text = "Sets"
setsHeader.TextColor3 = Color3.new(1,1,1)
setsHeader.TextXAlignment = Enum.TextXAlignment.Left
setsHeader.TextYAlignment = Enum.TextYAlignment.Top
setsHeader.Parent = sets
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(1,-32,0,-2)
cancelButton.Size = UDim2.new(0,34,0,34)
cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
cancelButton.ZIndex = 6
cancelButton.Text = ""
cancelButton.Modal = true
cancelButton.Parent = setPanel
-- Children of Cancel Button
local cancelImage = Instance.new("ImageLabel")
cancelImage.Name = "CancelImage"
cancelImage.BackgroundTransparency = 1
cancelImage.Image = "http://www.roblox.com/asset/?id=54135717"
cancelImage.Position = UDim2.new(0,-2,0,-2)
cancelImage.Size = UDim2.new(0,16,0,16)
cancelImage.ZIndex = 6
cancelImage.Parent = cancelButton
return setGui
end
local function createSetButton(text)
local setButton = Instance.new("TextButton")
if text then setButton.Text = text
else setButton.Text = "" end
setButton.AutoButtonColor = false
setButton.BackgroundTransparency = 1
setButton.BackgroundColor3 = Color3.new(1,1,1)
setButton.BorderSizePixel = 0
setButton.Size = UDim2.new(1,-5,0,18)
setButton.ZIndex = 6
setButton.Visible = false
setButton.Font = Enum.Font.Arial
setButton.FontSize = Enum.FontSize.Size18
setButton.TextColor3 = Color3.new(1,1,1)
setButton.TextXAlignment = Enum.TextXAlignment.Left
return setButton
end
local function buildSetButton(name, setId, setImageId, i, count)
local button = createSetButton(name)
button.Text = name
button.Name = "SetButton"
button.Visible = true
local setValue = Instance.new("IntValue")
setValue.Name = "SetId"
setValue.Value = setId
setValue.Parent = button
local setName = Instance.new("StringValue")
setName.Name = "SetName"
setName.Value = name
setName.Parent = button
return button
end
local function processCategory(sets)
local setButtons = {}
local numSkipped = 0
for i = 1, #sets do
if not showAdminCategories and sets[i].Name == "Beta" then
numSkipped = numSkipped + 1
else
setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
end
end
return setButtons
end
local function handleResize()
wait() -- neccessary to insure heartbeat happened
local itemPreview = setGui.SetPanel.ItemPreview
itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
end
local function makeInsertAssetButton()
local insertAssetButtonExample = Instance.new("Frame")
insertAssetButtonExample.Name = "InsertAssetButtonExample"
insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
insertAssetButtonExample.BackgroundTransparency = 1
insertAssetButtonExample.ZIndex = 6
insertAssetButtonExample.Visible = false
local assetId = Instance.new("IntValue")
assetId.Name = "AssetId"
assetId.Value = 0
assetId.Parent = insertAssetButtonExample
local assetName = Instance.new("StringValue")
assetName.Name = "AssetName"
assetName.Value = ""
assetName.Parent = insertAssetButtonExample
local button = Instance.new("TextButton")
button.Name = "Button"
button.Text = ""
button.Style = Enum.ButtonStyle.RobloxButton
button.Position = UDim2.new(0.025,0,0.025,0)
button.Size = UDim2.new(0.95,0,0.95,0)
button.ZIndex = 6
button.Parent = insertAssetButtonExample
local buttonImage = Instance.new("ImageLabel")
buttonImage.Name = "ButtonImage"
buttonImage.Image = ""
buttonImage.Position = UDim2.new(0,-7,0,-7)
buttonImage.Size = UDim2.new(1,14,1,14)
buttonImage.BackgroundTransparency = 1
buttonImage.ZIndex = 7
buttonImage.Parent = button
local configIcon = buttonImage:clone()
configIcon.Name = "ConfigIcon"
configIcon.Visible = false
configIcon.Position = UDim2.new(1,-23,1,-24)
configIcon.Size = UDim2.new(0,16,0,16)
configIcon.Image = ""
configIcon.ZIndex = 6
configIcon.Parent = insertAssetButtonExample
return insertAssetButtonExample
end
local function showLargePreview(insertButton)
if insertButton:FindFirstChild("AssetId") then
delay(0,function()
game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
end)
end
if insertButton:FindFirstChild("AssetName") then
setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
end
end
local function selectTerrainShape(shape)
if currTerrainDropDownFrame then
objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
end
end
local function createTerrainTypeButton(name, parent)
local dropDownTextButton = Instance.new("TextButton")
dropDownTextButton.Name = name .. "Button"
dropDownTextButton.Font = Enum.Font.ArialBold
dropDownTextButton.FontSize = Enum.FontSize.Size14
dropDownTextButton.BorderSizePixel = 0
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
dropDownTextButton.Text = name
dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.ZIndex = parent.ZIndex + 1
dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
dropDownTextButton.Position = UDim2.new(0,1,0,0)
dropDownTextButton.MouseEnter:connect(function()
dropDownTextButton.BackgroundTransparency = 0
dropDownTextButton.TextColor3 = Color3.new(0,0,0)
end)
dropDownTextButton.MouseLeave:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
end)
dropDownTextButton.MouseButton1Click:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
dropDownTextButton.Parent.Visible = false
end
selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
end)
return dropDownTextButton
end
local function createTerrainDropDownMenu(zIndex)
local dropDown = Instance.new("Frame")
dropDown.Name = "TerrainDropDown"
dropDown.BackgroundColor3 = Color3.new(0,0,0)
dropDown.BorderColor3 = Color3.new(1,0,0)
dropDown.Size = UDim2.new(0,200,0,0)
dropDown.Visible = false
dropDown.ZIndex = zIndex
dropDown.Parent = setGui
for i = 1, #terrainShapes do
local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
shapeButton.Parent = dropDown
dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
end
dropDown.MouseLeave:connect(function()
dropDown.Visible = false
end)
end
local function createDropDownMenuButton(parent)
local dropDownButton = Instance.new("ImageButton")
dropDownButton.Name = "DropDownButton"
dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509"
dropDownButton.BackgroundTransparency = 1
dropDownButton.Size = UDim2.new(0,16,0,16)
dropDownButton.Position = UDim2.new(1,-24,0,6)
dropDownButton.ZIndex = parent.ZIndex + 2
dropDownButton.Parent = parent
if not setGui:FindFirstChild("TerrainDropDown") then
createTerrainDropDownMenu(8)
end
dropDownButton.MouseButton1Click:connect(function()
setGui.TerrainDropDown.Visible = true
setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
currTerrainDropDownFrame = parent
end)
end
local function buildInsertButton()
local insertButton = makeInsertAssetButton()
insertButton.Name = "InsertAssetButton"
insertButton.Visible = true
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
createDropDownMenuButton(insertButton)
end
local lastEnter = nil
local mouseEnterCon = insertButton.MouseEnter:connect(function()
lastEnter = insertButton
delay(0.1,function()
if lastEnter == insertButton then
showLargePreview(insertButton)
end
end)
end)
return insertButton, mouseEnterCon
end
local function realignButtonGrid(columns)
local x = 0
local y = 0
for i = 1, #insertButtons do
insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
x = x + 1
if x >= columns then
x = 0
y = y + 1
end
end
end
local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
if visible then
insertFrame.AssetName.Value = name
insertFrame.AssetId.Value = assetId
local newImageUrl = SmallThumbnailUrl .. assetId
if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
delay(0,function()
game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
if insertFrame:findFirstChild("Button") then
insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
end
end)
end
table.insert(insertButtonCons,
insertFrame.Button.MouseButton1Click:connect(function()
-- special case for water, show water selection gui
local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
waterGui.Visible = isWaterSelected
if isWaterSelected then
objectSelected(name, tonumber(assetId), nil)
else
objectSelected(name, tonumber(assetId))
end
end)
)
insertFrame.Visible = true
else
insertFrame.Visible = false
end
end
local function loadSectionOfItems(setGui, rows, columns)
local pageSize = rows * columns
if arrayPosition > #contents then return end
local origArrayPos = arrayPosition
local yCopy = 0
for i = 1, pageSize + 1 do
if arrayPosition >= #contents + 1 then
break
end
local buttonCon
insertButtons[arrayPosition], buttonCon = buildInsertButton()
table.insert(insertButtonCons,buttonCon)
insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
arrayPosition = arrayPosition + 1
end
realignButtonGrid(columns)
local indexCopy = origArrayPos
for index = origArrayPos, arrayPosition do
if insertButtons[index] then
if contents[index] then
-- we don't want water to have a drop down button
if contents[index].Name == "Water" then
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
end
end
local assetId
if useAssetVersionId then
assetId = contents[index].AssetVersionId
else
assetId = contents[index].AssetId
end
setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
else
break
end
else
break
end
indexCopy = index
end
end
local function setSetIndex()
Data.Category[Data.CurrentCategory].Index = 0
rows = 7
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
contents = Data.Category[Data.CurrentCategory].Contents
if contents then
-- remove our buttons and their connections
for i = 1, #insertButtons do
insertButtons[i]:remove()
end
for i = 1, #insertButtonCons do
if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
end
insertButtonCons = {}
insertButtons = {}
arrayPosition = 1
loadSectionOfItems(setGui, rows, columns)
end
end
local function selectSet(button, setName, setId, setIndex)
if button and Data.Category[Data.CurrentCategory] ~= nil then
if button ~= Data.Category[Data.CurrentCategory].Button then
Data.Category[Data.CurrentCategory].Button = button
if SetCache[setId] == nil then
SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
end
Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
Data.Category[Data.CurrentCategory].SetName = setName
Data.Category[Data.CurrentCategory].SetId = setId
end
setSetIndex()
end
end
local function selectCategoryPage(buttons, page)
if buttons ~= Data.CurrentCategory then
if Data.CurrentCategory then
for key, button in pairs(Data.CurrentCategory) do
button.Visible = false
end
end
Data.CurrentCategory = buttons
if Data.Category[Data.CurrentCategory] == nil then
Data.Category[Data.CurrentCategory] = {}
if #buttons > 0 then
selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
end
else
Data.Category[Data.CurrentCategory].Button = nil
selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
end
end
end
local function selectCategory(category)
selectCategoryPage(category, 0)
end
local function resetAllSetButtonSelection()
local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
for i = 1, #setButtons do
if setButtons[i]:IsA("TextButton") then
setButtons[i].Selected = false
setButtons[i].BackgroundTransparency = 1
setButtons[i].TextColor3 = Color3.new(1,1,1)
setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
end
end
end
local function populateSetsFrame()
local currRow = 0
for i = 1, #userCategoryButtons do
local button = userCategoryButtons[i]
button.Visible = true
button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
button.Parent = setGui.SetPanel.Sets.SetsLists
if i == 1 then -- we will have this selected by default, so show it
button.Selected = true
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
end
button.MouseEnter:connect(function()
if not button.Selected then
button.BackgroundTransparency = 0
button.TextColor3 = Color3.new(0,0,0)
end
end)
button.MouseLeave:connect(function()
if not button.Selected then
button.BackgroundTransparency = 1
button.TextColor3 = Color3.new(1,1,1)
end
end)
button.MouseButton1Click:connect(function()
resetAllSetButtonSelection()
button.Selected = not button.Selected
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
end)
currRow = currRow + 1
end
local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
-- set first category as loaded for default
if buttons then
for i = 1, #buttons do
if buttons[i]:IsA("TextButton") then
selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
selectCategory(userCategoryButtons)
break
end
end
end
end
setGui = createSetGui()
waterGui, waterTypeChangedEvent = createWaterGui()
waterGui.Position = UDim2.new(0,55,0,0)
waterGui.Parent = setGui
setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
if prop == "AbsoluteSize" then
handleResize()
setSetIndex()
end
end)
local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
scrollFrame.Name = "ItemsFrame"
scrollFrame.ZIndex = 6
scrollFrame.Parent = setGui.SetPanel
scrollFrame.BackgroundTransparency = 1
drillDownSetZIndex(controlFrame,7)
controlFrame.Parent = setGui.SetPanel
controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
local debounce = false
controlFrame.ScrollBottom.Changed:connect(function(prop)
if controlFrame.ScrollBottom.Value == true then
if debounce then return end
debounce = true
loadSectionOfItems(setGui, rows, columns)
debounce = false
end
end)
local userData = {}
for id = 1, #userIdsForSets do
local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
if newUserData and #newUserData > 2 then
-- start at #3 to skip over My Decals and My Models for each account
for category = 3, #newUserData do
if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
table.insert(userData,1,newUserData[category])
else
table.insert(userData, newUserData[category])
end
end
end
end
if userData then
userCategoryButtons = processCategory(userData)
end
rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
populateSetsFrame()
insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
setGui.SetPanel.Visible = false
if dialogClosed then dialogClosed() end
end)
local setVisibilityFunction = function(visible)
if visible then
setGui.SetPanel.Visible = true
else
setGui.SetPanel.Visible = false
end
end
local getVisibilityFunction = function()
if setGui then
if setGui:FindFirstChild("SetPanel") then
return setGui.SetPanel.Visible
end
end
return false
end
return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
end
t.CreateTerrainMaterialSelector = function(size,position)
local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
local selectedButton = nil
local frame = Instance.new("Frame")
frame.Name = "TerrainMaterialSelector"
if size then
frame.Size = size
else
frame.Size = UDim2.new(0, 245, 0, 230)
end
if position then
frame.Position = position
end
frame.BorderSizePixel = 0
frame.BackgroundColor3 = Color3.new(0,0,0)
frame.Active = true
terrainMaterialSelectionChanged.Parent = frame
local waterEnabled = true -- todo: turn this on when water is ready
local materialToImageMap = {}
local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
if waterEnabled then
table.insert(materialNames,"Water")
end
local currentMaterial = 1
function getEnumFromName(choice)
if choice == "Grass" then return 1 end
if choice == "Sand" then return 2 end
if choice == "Erase" then return 0 end
if choice == "Brick" then return 3 end
if choice == "Granite" then return 4 end
if choice == "Asphalt" then return 5 end
if choice == "Iron" then return 6 end
if choice == "Aluminum" then return 7 end
if choice == "Gold" then return 8 end
if choice == "Plank" then return 9 end
if choice == "Log" then return 10 end
if choice == "Gravel" then return 11 end
if choice == "Cinder Block" then return 12 end
if choice == "Stone Wall" then return 13 end
if choice == "Concrete" then return 14 end
if choice == "Plastic (red)" then return 15 end
if choice == "Plastic (blue)" then return 16 end
if choice == "Water" then return 17 end
end
function getNameFromEnum(choice)
if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
if waterEnabled then
if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
end
end
local function updateMaterialChoice(choice)
currentMaterial = getEnumFromName(choice)
terrainMaterialSelectionChanged:Fire(currentMaterial)
end
-- we so need a better way to do this
for i,v in pairs(materialNames) do
materialToImageMap[v] = {}
if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112"
elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652"
elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537"
elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153"
elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038"
elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093"
elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995"
elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118"
elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848"
elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924"
elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015"
elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051"
elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206"
elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103"
elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804"
elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059"
elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474"
else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!!
end
end
local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
scrollFrame.Size = UDim2.new(0.85,0,1,0)
scrollFrame.Position = UDim2.new(0,0,0,0)
scrollFrame.Parent = frame
scrollUp.Parent = frame
scrollUp.Visible = true
scrollUp.Position = UDim2.new(1,-19,0,0)
scrollDown.Parent = frame
scrollDown.Visible = true
scrollDown.Position = UDim2.new(1,-19,1,-17)
local function goToNewMaterial(buttonWrap, materialName)
updateMaterialChoice(materialName)
buttonWrap.BackgroundTransparency = 0
selectedButton.BackgroundTransparency = 1
selectedButton = buttonWrap
end
local function createMaterialButton(name)
local buttonWrap = Instance.new("TextButton")
buttonWrap.Text = ""
buttonWrap.Size = UDim2.new(0,32,0,32)
buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
buttonWrap.BorderSizePixel = 0
buttonWrap.BackgroundTransparency = 1
buttonWrap.AutoButtonColor = false
buttonWrap.Name = tostring(name)
local imageButton = Instance.new("ImageButton")
imageButton.AutoButtonColor = false
imageButton.BackgroundTransparency = 1
imageButton.Size = UDim2.new(0,30,0,30)
imageButton.Position = UDim2.new(0,1,0,1)
imageButton.Name = tostring(name)
imageButton.Parent = buttonWrap
imageButton.Image = materialToImageMap[name].Regular
local enumType = Instance.new("NumberValue")
enumType.Name = "EnumType"
enumType.Parent = buttonWrap
enumType.Value = 0
imageButton.MouseEnter:connect(function()
buttonWrap.BackgroundTransparency = 0
end)
imageButton.MouseLeave:connect(function()
if selectedButton ~= buttonWrap then
buttonWrap.BackgroundTransparency = 1
end
end)
imageButton.MouseButton1Click:connect(function()
if selectedButton ~= buttonWrap then
goToNewMaterial(buttonWrap, tostring(name))
end
end)
return buttonWrap
end
for i = 1, #materialNames do
local imageButton = createMaterialButton(materialNames[i])
if materialNames[i] == "Grass" then -- always start with grass as the default
selectedButton = imageButton
imageButton.BackgroundTransparency = 0
end
imageButton.Parent = scrollFrame
end
local forceTerrainMaterialSelection = function(newMaterialType)
if not newMaterialType then return end
if currentMaterial == newMaterialType then return end
local matName = getNameFromEnum(newMaterialType)
local buttons = scrollFrame:GetChildren()
for i = 1, #buttons do
if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
if string.find(buttons[i].Name, matName) then
goToNewMaterial(buttons[i],matName)
return
end
end
end
frame.Changed:connect(function ( prop )
if prop == "AbsoluteSize" then
recalculateScroll()
end
end)
recalculateScroll()
return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
end
t.CreateLoadingFrame = function(name,size,position)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053")
local loadingFrame = Instance.new("Frame")
loadingFrame.Name = "LoadingFrame"
loadingFrame.Style = Enum.FrameStyle.RobloxRound
if size then loadingFrame.Size = size
else loadingFrame.Size = UDim2.new(0,300,0,160) end
if position then loadingFrame.Position = position
else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
local loadingBar = Instance.new("Frame")
loadingBar.Name = "LoadingBar"
loadingBar.BackgroundColor3 = Color3.new(0,0,0)
loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
loadingBar.Position = UDim2.new(0,0,0,41)
loadingBar.Size = UDim2.new(1,0,0,30)
loadingBar.Parent = loadingFrame
local loadingGreenBar = Instance.new("ImageLabel")
loadingGreenBar.Name = "LoadingGreenBar"
loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053"
loadingGreenBar.Position = UDim2.new(0,0,0,0)
loadingGreenBar.Size = UDim2.new(0,0,1,0)
loadingGreenBar.Visible = false
loadingGreenBar.Parent = loadingBar
local loadingPercent = Instance.new("TextLabel")
loadingPercent.Name = "LoadingPercent"
loadingPercent.BackgroundTransparency = 1
loadingPercent.Position = UDim2.new(0,0,1,0)
loadingPercent.Size = UDim2.new(1,0,0,14)
loadingPercent.Font = Enum.Font.Arial
loadingPercent.Text = "0%"
loadingPercent.FontSize = Enum.FontSize.Size14
loadingPercent.TextColor3 = Color3.new(1,1,1)
loadingPercent.Parent = loadingBar
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(0.5,-60,1,-40)
cancelButton.Size = UDim2.new(0,120,0,40)
cancelButton.Font = Enum.Font.Arial
cancelButton.FontSize = Enum.FontSize.Size18
cancelButton.TextColor3 = Color3.new(1,1,1)
cancelButton.Text = "Cancel"
cancelButton.Style = Enum.ButtonStyle.RobloxButton
cancelButton.Parent = loadingFrame
local loadingName = Instance.new("TextLabel")
loadingName.Name = "loadingName"
loadingName.BackgroundTransparency = 1
loadingName.Size = UDim2.new(1,0,0,18)
loadingName.Position = UDim2.new(0,0,0,2)
loadingName.Font = Enum.Font.Arial
loadingName.Text = name
loadingName.TextColor3 = Color3.new(1,1,1)
loadingName.TextStrokeTransparency = 1
loadingName.FontSize = Enum.FontSize.Size18
loadingName.Parent = loadingFrame
local cancelButtonClicked = Instance.new("BindableEvent")
cancelButtonClicked.Name = "CancelButtonClicked"
cancelButtonClicked.Parent = cancelButton
cancelButton.MouseButton1Click:connect(function()
cancelButtonClicked:Fire()
end)
local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
if percent and type(percent) ~= "number" then
error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
end
local newSize = nil
if percent < 0 then
newSize = UDim2.new(0,0,1,0)
elseif percent > 1 then
newSize = UDim2.new(1,0,1,0)
else
newSize = UDim2.new(percent,0,1,0)
end
if tweenAction then
if not tweenLength then
error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
end
if (newSize.X.Scale > 0) then
loadingGreenBar.Visible = true
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true)
else
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true,
function()
if (newSize.X.Scale < 0) then
loadingGreenBar.Visible = false
end
end)
end
else
loadingGreenBar.Size = newSize
loadingGreenBar.Visible = (newSize.X.Scale > 0)
end
end
loadingGreenBar.Changed:connect(function(prop)
if prop == "Size" then
loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
end
end)
return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
end
t.CreatePluginFrame = function (name,size,position,scrollable,parent)
function createMenuButton(size,position,text,fontsize,name,parent)
local button = Instance.new("TextButton",parent)
button.AutoButtonColor = false
button.Name = name
button.BackgroundTransparency = 1
button.Position = position
button.Size = size
button.Font = Enum.Font.ArialBold
button.FontSize = fontsize
button.Text = text
button.TextColor3 = Color3.new(1,1,1)
button.BorderSizePixel = 0
button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
button.MouseEnter:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 1
end)
return button
end
local dragBar = Instance.new("Frame",parent)
dragBar.Name = tostring(name) .. "DragBar"
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
dragBar.BorderColor3 = Color3.new(0,0,0)
if size then
dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
else
dragBar.Size = UDim2.new(0,183,0,20)
end
if position then
dragBar.Position = position
end
dragBar.Active = true
dragBar.Draggable = true
--dragBar.Visible = false
dragBar.MouseEnter:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
end)
dragBar.MouseLeave:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end)
-- plugin name label
local pluginNameLabel = Instance.new("TextLabel",dragBar)
pluginNameLabel.Name = "BarNameLabel"
pluginNameLabel.Text = " " .. tostring(name)
pluginNameLabel.TextColor3 = Color3.new(1,1,1)
pluginNameLabel.TextStrokeTransparency = 0
pluginNameLabel.Size = UDim2.new(1,0,1,0)
pluginNameLabel.Font = Enum.Font.ArialBold
pluginNameLabel.FontSize = Enum.FontSize.Size18
pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
pluginNameLabel.BackgroundTransparency = 1
-- close button
local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
local closeEvent = Instance.new("BindableEvent")
closeEvent.Name = "CloseEvent"
closeEvent.Parent = closeButton
closeButton.MouseButton1Click:connect(function ()
closeEvent:Fire()
closeButton.BackgroundTransparency = 1
end)
-- help button
local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
local helpFrame = Instance.new("Frame",dragBar)
helpFrame.Name = "HelpFrame"
helpFrame.BackgroundColor3 = Color3.new(0,0,0)
helpFrame.Size = UDim2.new(0,300,0,552)
helpFrame.Position = UDim2.new(1,5,0,0)
helpFrame.Active = true
helpFrame.BorderSizePixel = 0
helpFrame.Visible = false
helpButton.MouseButton1Click:connect(function( )
helpFrame.Visible = not helpFrame.Visible
if helpFrame.Visible then
helpButton.Selected = true
helpButton.BackgroundTransparency = 0
local screenGui = getScreenGuiAncestor(helpFrame)
if screenGui then
if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
else -- position on right hand side
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpButton.Selected = false
helpButton.BackgroundTransparency = 1
end
end)
local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
local minimizeFrame = Instance.new("Frame",dragBar)
minimizeFrame.Name = "MinimizeFrame"
minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
minimizeFrame.BorderColor3 = Color3.new(0,0,0)
minimizeFrame.Position = UDim2.new(0,0,1,0)
if size then
minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
else
minimizeFrame.Size = UDim2.new(0,183,0,50)
end
minimizeFrame.Visible = false
local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
minimizeBigButton.Name = "MinimizeButton"
minimizeBigButton.Size = UDim2.new(0,100,0,40)
minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
minimizeBigButton.Font = Enum.Font.ArialBold
minimizeBigButton.FontSize = Enum.FontSize.Size18
minimizeBigButton.TextColor3 = Color3.new(1,1,1)
minimizeBigButton.Text = "Show"
local separatingLine = Instance.new("Frame",dragBar)
separatingLine.Name = "SeparatingLine"
separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
separatingLine.BorderSizePixel = 0
separatingLine.Position = UDim2.new(1,-18,0.5,-7)
separatingLine.Size = UDim2.new(0,1,0,14)
local otherSeparatingLine = separatingLine:clone()
otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
otherSeparatingLine.Parent = dragBar
local widgetContainer = Instance.new("Frame",dragBar)
widgetContainer.Name = "WidgetContainer"
widgetContainer.BackgroundTransparency = 1
widgetContainer.Position = UDim2.new(0,0,1,0)
widgetContainer.BorderColor3 = Color3.new(0,0,0)
if not scrollable then
widgetContainer.BackgroundTransparency = 0
widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
end
if size then
if scrollable then
widgetContainer.Size = size
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
end
else
if scrollable then
widgetContainer.Size = UDim2.new(0,163,0,400)
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
end
end
if position then
widgetContainer.Position = position + UDim2.new(0,0,0,20)
end
local frame,control,verticalDragger = nil
if scrollable then
--frame for widgets
frame,control = t.CreateTrueScrollingFrame()
frame.Size = UDim2.new(1, 0, 1, 0)
frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
frame.BorderColor3 = Color3.new(0,0,0)
frame.Active = true
frame.Parent = widgetContainer
control.Parent = dragBar
control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
control.BorderSizePixel = 0
control.BackgroundTransparency = 0
control.Position = UDim2.new(1,-21,1,1)
if size then
control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
else
control.Size = UDim2.new(0,21,0,400)
end
control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
local fakeLine = Instance.new("Frame",control)
fakeLine.Name = "FakeLine"
fakeLine.BorderSizePixel = 0
fakeLine.BackgroundColor3 = Color3.new(0,0,0)
fakeLine.Size = UDim2.new(0,1,1,1)
fakeLine.Position = UDim2.new(1,0,0,0)
verticalDragger = Instance.new("TextButton",widgetContainer)
verticalDragger.ZIndex = 2
verticalDragger.AutoButtonColor = false
verticalDragger.Name = "VerticalDragger"
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
verticalDragger.BorderColor3 = Color3.new(0,0,0)
verticalDragger.Size = UDim2.new(1,20,0,20)
verticalDragger.Position = UDim2.new(0,0,1,0)
verticalDragger.Active = true
verticalDragger.Text = ""
local scrubFrame = Instance.new("Frame",verticalDragger)
scrubFrame.Name = "ScrubFrame"
scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
scrubFrame.BorderSizePixel = 0
scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
scrubFrame.Size = UDim2.new(0,10,0,1)
scrubFrame.ZIndex = 5
local scrubTwo = scrubFrame:clone()
scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
scrubTwo.Parent = verticalDragger
local scrubThree = scrubFrame:clone()
scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
scrubThree.Parent = verticalDragger
local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
areaSoak.Name = "AreaSoak"
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.BackgroundTransparency = 1
areaSoak.BorderSizePixel = 0
areaSoak.Text = ""
areaSoak.ZIndex = 10
areaSoak.Visible = false
areaSoak.Active = true
local draggingVertical = false
local startYPos = nil
verticalDragger.MouseEnter:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
end)
verticalDragger.MouseLeave:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
end)
verticalDragger.MouseButton1Down:connect(function(x,y)
draggingVertical = true
areaSoak.Visible = true
startYPos = y
end)
areaSoak.MouseButton1Up:connect(function ( )
draggingVertical = false
areaSoak.Visible = false
end)
areaSoak.MouseMoved:connect(function(x,y)
if not draggingVertical then return end
local yDelta = y - startYPos
if not control.ScrollDownButton.Visible and yDelta > 0 then
return
end
if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
control.Size = UDim2.new (0,21,0,150)
return
end
startYPos = y
if widgetContainer.Size.Y.Offset + yDelta >= 0 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
end
end)
end
local function switchMinimize()
minimizeFrame.Visible = not minimizeFrame.Visible
if scrollable then
frame.Visible = not frame.Visible
verticalDragger.Visible = not verticalDragger.Visible
control.Visible = not control.Visible
else
widgetContainer.Visible = not widgetContainer.Visible
end
if minimizeFrame.Visible then
minimizeButton.Text = "+"
else
minimizeButton.Text = "-"
end
end
minimizeBigButton.MouseButton1Click:connect(function ( )
switchMinimize()
end)
minimizeButton.MouseButton1Click:connect(function( )
switchMinimize()
end)
if scrollable then
return dragBar, frame, helpFrame, closeEvent
else
return dragBar, widgetContainer, helpFrame, closeEvent
end
end
t.Help =
function(funcNameOrFunc)
--input argument can be a string or a function. Should return a description (of arguments and expected side effects)
if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
return "Function CreatePropertyDropDownMenu. " ..
"Arguments: (instance, propertyName, enumType). " ..
"Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
end
if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
return "Function CreateDropDownMenu. " ..
"Arguments: (items, onItemSelected). " ..
"Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
end
if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
return "Function CreateMessageDialog. " ..
"Arguments: (title, message, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
end
if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
return "Function CreateStyledMessageDialog. " ..
"Arguments: (title, message, style, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
end
if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
return "Function GetFontHeight. " ..
"Arguments: (font, fontSize). " ..
"Side effect: returns the size in pixels of the given font + fontSize"
end
if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
end
if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
return "Function CreateScrollingFrame. " ..
"Arguments: (orderList, style) " ..
"Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
end
if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
return "Function CreateTrueScrollingFrame. " ..
"Arguments: (nil) " ..
"Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
end
if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
return "Function AutoTruncateTextObject. " ..
"Arguments: (textLabel) " ..
"Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
end
if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
return "Function CreateSlider. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then
return "Function CreateSliderNew. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
return "Function CreateLoadingFrame. " ..
"Arguments: (name, size, position) " ..
"Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
end
if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
return "Function CreateTerrainMaterialSelector. " ..
"Arguments: (size, position) " ..
"Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
end
end
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
local RbxGui,msg = t
if not RbxGui then print("could not find RbxGui!") return end
--- Begin Locals
waitForChild(game,"Players")
-- don't do anything if we are in an empty game
if #game.Players:GetChildren() < 1 then
game.Players.ChildAdded:wait()
end
local tilde = "~"
local backquote = "`"
game:GetService("GuiService"):AddKey(tilde) -- register our keys
game:GetService("GuiService"):AddKey(backquote)
local player = game.Players.LocalPlayer
local backpack = script.Parent.Backpack
local screen = script.Parent
local openCloseDebounce = false
local backpackItems = {}
local buttons = {}
local debounce = false
local guiTweenSpeed = 1
local browsingMenu = false
local mouseEnterCons = {}
local mouseClickCons = {}
local characterChildAddedCon = nil
local characterChildRemovedCon = nil
local backpackAddCon = nil
local humanoidDiedCon = nil
local backpackButtonClickCon = nil
local guiServiceKeyPressCon = nil
local playerBackpack = player.Backpack
local gearPreview = backpack.Gear.GearPreview
local scroller = backpack.Gear.GearGridScrollingArea
local currentLoadout = backpack.Parent.CurrentLoadout
local backpackButton = backpack.Parent.ControlFrame.BackpackButton
local gearButton = backpack.Gear.GearGrid.GearButton
local grid = backpack.Gear.GearGrid
local searchBox = backpack.SearchFrame.SearchBoxFrame.SearchBox
local searchButton = backpack.SearchFrame.SearchButton
local resetFrame = backpack.SearchFrame
local resetButton = backpack.SearchFrame.ResetButton
local swapSlot = backpack.SwapSlot
-- creating scroll bar early as to make sure items get placed correctly
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid")
scrollFrame.Position = UDim2.new(0,0,0,30)
scrollFrame.Size = UDim2.new(1,0,1,-30)
scrollFrame.Parent = backpack.Gear.GearGrid
local scrollBar = Instance.new("Frame")
scrollBar.Name = "ScrollBar"
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
scrollBar.Position = UDim2.new(0,0,0,18)
scrollBar.Parent = scroller
scrollDown.Position = UDim2.new(0,0,1,-17)
scrollUp.Parent = scroller
scrollDown.Parent = scroller
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
local LoadoutButton = Instance.new("TextButton")
LoadoutButton.RobloxLocked = true
LoadoutButton.Name = "LoadoutButton"
LoadoutButton.Font = Enum.Font.ArialBold
LoadoutButton.FontSize = Enum.FontSize.Size14
LoadoutButton.Position = UDim2.new(0,0,0,0)
LoadoutButton.Size = UDim2.new(1,0,0,32)
LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
LoadoutButton.Text = "Loadout #1"
LoadoutButton.TextColor3 = Color3.new(1,1,1)
LoadoutButton.Parent = scrollFrameLoadout
local LoadoutButtonTwo = LoadoutButton:clone()
LoadoutButtonTwo.Text = "Loadout #2"
LoadoutButtonTwo.Parent = scrollFrameLoadout
local LoadoutButtonThree = LoadoutButton:clone()
LoadoutButtonThree.Text = "Loadout #3"
LoadoutButtonThree.Parent = scrollFrameLoadout
local LoadoutButtonFour = LoadoutButton:clone()
LoadoutButtonFour.Text = "Loadout #4"
LoadoutButtonFour.Parent = scrollFrameLoadout
local scrollBarLoadout = Instance.new("Frame")
scrollBarLoadout.Name = "ScrollBarLoadout"
scrollBarLoadout.BackgroundTransparency = 0.9
scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
scrollBarLoadout.BorderSizePixel = 0
scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
scrollBarLoadout.Position = UDim2.new(0,0,0,18)
scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
-- Begin Functions
function removeFromMap(map,object)
for i = 1, #map do
if map[i] == object then
table.remove(map,i)
break
end
end
end
function robloxLock(instance)
instance.RobloxLocked = true
children = instance:GetChildren()
if children then
for i, child in ipairs(children) do
robloxLock(child)
end
end
end
function resize()
local size = 0
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
size = gearPreview.AbsoluteSize.X * 0.75
else
size = gearPreview.AbsoluteSize.Y * 0.75
end
gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
resizeGrid()
end
function addToGrid(child)
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
return
end
end
if child:FindFirstChild("RobloxBuildTool") then return end
for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
if v == child then return end
end
table.insert(backpackItems,child)
local changeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if buttons[child] then
if buttons[child].Image == "" then
buttons[child].GearText.Text = child.Name
end
end
end
end)
local ancestryCon = nil
ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
local thisObject = nil
for k,v in pairs(backpackItems) do
if v == child then
thisObject = v
break
end
end
waitForProperty(player,"Character")
waitForChild(player,"Backpack")
if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
if ancestryCon then ancestryCon:disconnect() end
if changeCon then changeCon:disconnect() end
for k,v in pairs(backpackItems) do
if v == thisObject then
if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
buttons[v].Parent = nil
buttons[v] = nil
break
end
end
removeFromMap(backpackItems,thisObject)
resizeGrid()
else
resizeGrid()
end
updateGridActive()
end)
resizeGrid()
end
function buttonClick(button)
if button:FindFirstChild("UnequipContextMenu") and not button.Active then
button.UnequipContextMenu.Visible = true
browsingMenu = true
end
end
function previewGear(button)
if not browsingMenu then
gearPreview.GearImage.Image = button.Image
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
end
end
function findEmptySlot()
local smallestNum = nil
local loadout = currentLoadout:GetChildren()
for i = 1, #loadout do
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
local frameNum = tonumber(string.sub(loadout[i].Name,5))
if frameNum == 0 then frameNum = 10 end
if not smallestNum or (smallestNum > frameNum) then
smallestNum = frameNum
end
end
end
if smallestNum == 10 then smallestNum = 0 end
return smallestNum
end
function checkForSwap(button,x,y)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
swapGearSlot(slot,button)
return true
end
end
end
end
return false
end
function resizeGrid()
for k,v in pairs(backpackItems) do
if not v:FindFirstChild("RobloxBuildTool") then
if not buttons[v] then
local buttonClone = gearButton:clone()
buttonClone.Parent = grid.ScrollingFrame
buttonClone.Visible = true
buttonClone.Image = v.TextureId
if buttonClone.Image == "" then
buttonClone.GearText.Text = v.Name
end
buttonClone.GearReference.Value = v
buttonClone.Draggable = true
buttons[v] = buttonClone
local unequipMenu = getGearContextMenu()
unequipMenu.Visible = false
unequipMenu.Parent = buttonClone
local beginPos = nil
buttonClone.DragBegin:connect(function(value)
buttonClone.ZIndex = 9
beginPos = value
end)
buttonClone.DragStopped:connect(function(x,y)
if beginPos ~= buttonClone.Position then
buttonClone.ZIndex = 1
if not checkForSwap(buttonClone,x,y) then
buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
buttonClone.Draggable = false
delay(0.5,function()
buttonClone.Draggable = true
end)
else
buttonClone.Position = beginPos
end
end
end)
local clickTime = tick()
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
local newClickTime = tick()
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
local slot = findEmptySlot()
if slot then
buttonClone.ZIndex = 1
swapGearSlot(slot,buttonClone)
end
else
buttonClick(buttonClone)
end
clickTime = newClickTime
end)
end
end
end
recalculateScroll()
end
function showPartialGrid(subset)
resetFrame.Visible = true
for k,v in pairs(buttons) do
v.Parent = nil
end
for k,v in pairs(subset) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function showEntireGrid()
resetFrame.Visible = false
for k,v in pairs(buttons) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function inLoadout(gear)
local children = currentLoadout:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
local button = children[i]:GetChildren()
if #button > 0 then
if button[1].GearReference.Value and button[1].GearReference.Value == gear then
return true
end
end
end
end
return false
end
function updateGridActive()
for k,v in pairs(backpackItems) do
if buttons[v] then
local gear = nil
local gearRef = buttons[v]:FindFirstChild("GearReference")
if gearRef then gear = gearRef.Value end
if not gear then
buttons[v].Active = false
elseif inLoadout(gear) then
buttons[v].Active = false
else
buttons[v].Active = true
end
end
end
end
function centerGear(loadoutChildren)
local gearButtons = {}
local lastSlotAdd = nil
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function spreadOutGear(loadoutChildren)
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
if slot == 0 then slot = 10 end
loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
end
function openCloseBackpack(close)
if openCloseDebounce then return end
openCloseDebounce = true
local visible = not backpack.Visible
if visible and not close then
updateGridActive()
local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
backpack.Visible = true
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 0.5
end
end
spreadOutGear(loadoutChildren)
end,
function()
backpack.Visible = false
end)
end)
backpackButton.Selected = true
backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
delay(guiTweenSpeed/2 + 0.01,
function()
local children = backpack:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
children[i].Visible = true
end
end
resizeGrid()
resize()
openCloseDebounce = false
end)
else
backpackButton.Selected = false
local children = backpack:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
children[i].Visible = false
end
end
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 1
end
end
centerGear(loadoutChildren)
backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
delay(guiTweenSpeed/2 + 0.01,
function()
backpack.Visible = true
resizeGrid()
resize()
pcall(function() game.GuiService:RemoveCenterDialog(backpack) end)
openCloseDebounce = false
end)
end
end
function loadoutCheck(child, selectState)
if not child:IsA("ImageButton") then return end
for k,v in pairs(backpackItems) do
if buttons[v] then
if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
if buttons[v].GearReference.Value == child.GearReference.Value then
buttons[v].Active = selectState
break
end
end
end
end
end
function clearPreview()
gearPreview.GearImage.Image = ""
gearPreview.GearStats.GearName.Text = ""
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
stuff[i].Parent = playerBackpack
end
end
end
function equipGear(physGear)
removeAllEquippedGear(physGear)
physGear.Parent = player.Character
updateGridActive()
end
function unequipGear(physGear)
physGear.Parent = playerBackpack
updateGridActive()
end
function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
function swapGearSlot(slot,gearButton)
if not swapSlot.Value then -- signal loadout to swap a gear out
swapSlot.Slot.Value = slot
swapSlot.GearButton.Value = gearButton
swapSlot.Value = true
updateGridActive()
end
end
local UnequipGearMenuClick = function(element, menu)
if type(element.Action) ~= "number" then return end
local num = element.Action
if num == 1 then -- remove from loadout
unequipGear(menu.Parent.GearReference.Value)
local inventoryButton = menu.Parent
local gearToUnequip = inventoryButton.GearReference.Value
local loadoutChildren = currentLoadout:GetChildren()
local slot = -1
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local button = loadoutChildren[i]:GetChildren()
if button[1] and button[1].GearReference.Value == gearToUnequip then
slot = button[1].SlotNumber.Text
break
end
end
end
swapGearSlot(slot,nil)
end
end
-- these next two functions are used to stop any use of backpack while the player is dead (can cause issues)
function activateBackpack()
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 1
end
end
backpackButtonClickCon = backpackButton.MouseButton1Click:connect(function() openCloseBackpack() end)
guiServiceKeyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key)
if key == tilde or key == backquote then
openCloseBackpack()
end
end)
end
function deactivateBackpack()
if backpackButtonClickCon then backpackButtonClickCon:disconnect() end
if guiServiceKeyPressCon then guiServiceKeyPressCon:disconnect() end
openCloseBackpack(true)
end
function setupCharacterConnections()
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
-- make sure we get all the children
local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
if characterChildAddedCon then characterChildAddedCon:disconnect() end
characterChildAddedCon =
game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
addToGrid(child)
updateGridActive()
end)
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
characterChildRemovedCon =
game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
updateGridActive()
end)
if humanoidDiedCon then humanoidDiedCon:disconnect() end
local localPlayer = game.Players.LocalPlayer
waitForProperty(localPlayer,"Character")
waitForChild(localPlayer.Character,"Humanoid")
humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(function() deactivateBackpack() end)
activateBackpack()
wait()
centerGear(currentLoadout:GetChildren())
end
function removeCharacterConnections()
if characterChildAddedCon then characterChildAddedCon:disconnect() end
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
if backpackAddCon then backpackAddCon:disconnect() end
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function splitByWhiteSpace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 2 then
table.insert(terms,token)
end
end
return terms
end
function filterGear(searchTerm)
string.lower(searchTerm)
searchTerm = trim(searchTerm)
if string.len(searchTerm) < 2 then return nil end
local terms = splitByWhiteSpace(searchTerm)
local filteredGear = {}
for k,v in pairs(backpackItems) do
if buttons[v] then
local gearString = string.lower(buttons[v].GearReference.Value.Name)
gearString = trim(gearString)
for i = 1, #terms do
if string.match(gearString,terms[i]) then
table.insert(filteredGear,buttons[v])
break
end
end
end
end
return filteredGear
end
function showSearchGear()
local searchText = searchBox.Text
searchBox.Text = "Search..."
local filteredButtons = filterGear(searchText)
if filteredButtons and #filteredButtons > 0 then
showPartialGrid(filteredButtons)
else
showEntireGrid()
end
end
function nukeBackpack()
while #buttons > 0 do
table.remove(buttons)
end
buttons = {}
while #backpackItems > 0 do
table.remove(backpackItems)
end
backpackItems = {}
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
for i = 1, #scrollingFrameChildren do
scrollingFrameChildren[i]:remove()
end
end
function getGearContextMenu()
local gearContextMenu = Instance.new("Frame")
gearContextMenu.Active = true
gearContextMenu.Name = "UnequipContextMenu"
gearContextMenu.Size = UDim2.new(0,115,0,70)
gearContextMenu.Position = UDim2.new(0,-16,0,-16)
gearContextMenu.BackgroundTransparency = 1
gearContextMenu.Visible = false
local gearContextMenuButton = Instance.new("TextButton")
gearContextMenuButton.Name = "UnequipContextMenuButton"
gearContextMenuButton.Text = ""
gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
gearContextMenuButton.ZIndex = 4
gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
gearContextMenuButton.Visible = true
gearContextMenuButton.Parent = gearContextMenu
local elementHeight = 12
local contextMenuElements = {}
local contextMenuElementsName = {"Remove Hotkey"}
for i = 1, #contextMenuElementsName do
local element = {}
element.Type = "Button"
element.Text = contextMenuElementsName[i]
element.Action = i
element.DoIt = UnequipGearMenuClick
table.insert(contextMenuElements,element)
end
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == "Button" then
local button = Instance.new("TextButton")
button.Name = "UnequipContextButton" .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = " " .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.Position = UDim2.new(0,0,0,elementHeight * i)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 4
button.Parent = gearContextMenuButton
button.MouseButton1Click:connect(function()
if button.Active and not gearContextMenu.Parent.Active then
local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
browsingMenu = false
gearContextMenu.Visible = false
clearHighlight(button)
clearPreview()
end
end)
button.MouseEnter:connect(function()
if button.Active and gearContextMenu.Parent.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active and gearContextMenu.Parent.Active then
clearHighlight(button)
end
end)
contextElement.Button = button
contextElement.Element = button
elseif element.Type == "Label" then
local frame = Instance.new("Frame")
frame.Name = "ContextLabel" .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new("TextLabel")
label.Name = "Text1"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.0, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 4
label.Parent = frame
element.Label1 = label
if element.GetText2 then
label = Instance.new("TextLabel")
label.Name = "Text2"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Right
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.5, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 4
label.Parent = frame
element.Label2 = label
end
frame.Parent = gearContextMenuButton
element.Label = frame
element.Element = frame
end
end
gearContextMenu.ZIndex = 4
gearContextMenu.MouseLeave:connect(function()
browsingMenu = false
gearContextMenu.Visible = false
clearPreview()
end)
robloxLock(gearContextMenu)
return gearContextMenu
end
local backpackChildren = player.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
------------------------- Start Lifelong Connections -----------------------
screen.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if debounce then return end
debounce = true
wait()
resize()
resizeGrid()
debounce = false
end
end)
currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
currentLoadout.DescendantAdded:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
centerGear(currentLoadout:GetChildren())
end
end)
currentLoadout.DescendantRemoving:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
wait()
centerGear(currentLoadout:GetChildren())
end
end)
grid.MouseEnter:connect(function() clearPreview() end)
grid.MouseLeave:connect(function() clearPreview() end)
player.CharacterRemoving:connect(function()
removeCharacterConnections()
nukeBackpack()
end)
player.CharacterAdded:connect(function() setupCharacterConnections() end)
player.ChildAdded:connect(function(child)
if child:IsA("Backpack") then
playerBackpack = child
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
end)
swapSlot.Changed:connect(function()
if not swapSlot.Value then
updateGridActive()
end
end)
searchBox.FocusLost:connect(function(enterPressed)
if enterPressed then
showSearchGear()
end
end)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
loadoutChildren[i].ChildRemoved:connect(function()
updateGridActive()
end)
loadoutChildren[i].ChildAdded:connect(function()
updateGridActive()
end)
end
end
searchButton.MouseButton1Click:connect(function() showSearchGear() end)
resetButton.MouseButton1Click:connect(function() showEntireGrid() end)
------------------------- End Lifelong Connections -----------------------
resize()
resizeGrid()
-- make sure any items in the loadout are accounted for in inventory
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
loadoutCheck(loadoutChildren[i], false)
end
if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
-- make sure that inventory is listening to gear reparenting
if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
setupCharacterConnections()
end
if not backpackAddCon then
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
-- flip it on if we are good
backpackButton.Visible = true
recalculateScrollLoadout()
-
false
BackpackScript
-- fixed by iagoMAO#6808, any bugs report to me. --
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
--- Begin Locals
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
--[[waitForChild(game, "LocalBackpack")
game.LocalBackpack:SetOldSchoolBackpack(false)--]]
waitForChild(script.Parent, "CurrentLoadout")
local currentLoadout = script.Parent.CurrentLoadout
local maxNumLoadoutItems = 10
waitForChild(currentLoadout.Parent,"Backpack")
local guiBackpack = currentLoadout.Parent.Backpack
local characterChildAddedCon = nil
local keyPressCon = nil
local backpackChildCon = nil
local debounce = script.Parent.CurrentLoadout.Debounce
local waitingOnEnlarge = nil
local enlargeFactor = 1.18
local buttonSizeEnlarge = UDim2.new(1 * enlargeFactor,0,1 * enlargeFactor,0)
local buttonSizeNormal = UDim2.new(1,0,1,0)
local enlargeOverride = true
local guiTweenSpeed = 0.5
for i = 0, 9 do
game:GetService("GuiService"):AddKey(tostring(i)) -- register our keys
end
local gearSlots = {}
for i = 1, maxNumLoadoutItems do
gearSlots[i] = "empty"
end
local inventory = {}
local lastLoadout = {}
--- End Locals
-- Begin Functions
local function kill(prop,con,gear)
if con then con:disconnect() end
if prop == true and gear then
reorganizeLoadout(gear,false)
end
end
function removeGear(gear)
local emptySlot = nil
for i = 1, #gearSlots do
if gearSlots[i] == gear and gear.Parent ~= nil then
emptySlot = i
break
end
end
if emptySlot then
if gearSlots[emptySlot].GearReference.Value then
if gearSlots[emptySlot].GearReference.Value.Parent == game.Players.LocalPlayer.Character then -- if we currently have this equipped, unequip it
gearSlots[emptySlot].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack
end
if gearSlots[emptySlot].GearReference.Value:IsA("HopperBin") and gearSlots[emptySlot].GearReference.Value.Active then -- this is an active hopperbin
gearSlots[emptySlot].GearReference.Value:Disable()
gearSlots[emptySlot].GearReference.Value.Active = false
end
end
gearSlots[emptySlot] = "empty"
local centerizeX = gear.Size.X.Scale/2
local centerizeY = gear.Size.Y.Scale/2
gear:TweenSizeAndPosition(UDim2.new(0,0,0,0),
UDim2.new(gear.Position.X.Scale + centerizeX,gear.Position.X.Offset,gear.Position.Y.Scale + centerizeY,gear.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/4,true)
delay(guiTweenSpeed/2,
function()
gear:remove()
end)
end
end
function insertGear(gear, addToSlot)
local pos = nil
if not addToSlot then
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then
pos = i
break
end
end
if pos == 1 and gearSlots[1] ~= "empty" then gear:remove() return end -- we are currently full, can't add in
else
pos = addToSlot
-- push all gear down one slot
local start = 1
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then
start = i
break
end
end
for i = start, pos + 1, -1 do
gearSlots[i] = gearSlots[i - 1]
if i == 10 then
gearSlots[i].SlotNumber.Text = "0"
gearSlots[i].SlotNumberDownShadow.Text = "0"
gearSlots[i].SlotNumberUpShadow.Text = "0"
else
gearSlots[i].SlotNumber.Text = i
gearSlots[i].SlotNumberDownShadow.Text = i
gearSlots[i].SlotNumberUpShadow.Text = i
end
end
end
gearSlots[pos] = gear
if pos ~= maxNumLoadoutItems then
if(type(tostring(pos)) == "string") then
local posString = tostring(pos)
gear.SlotNumber.Text = posString
gear.SlotNumberDownShadow.Text = posString
gear.SlotNumberUpShadow.Text = posString
end
else -- tenth gear doesn't follow mathematical pattern :(
gear.SlotNumber.Text = "0"
gear.SlotNumberDownShadow.Text = "0"
gear.SlotNumberUpShadow.Text = "0"
end
gear.Visible = true
local con = nil
con = gear.Kill.Changed:connect(function(prop) kill(prop,con,gear) end)
end
function reorganizeLoadout(gear, inserting, equipped, addToSlot)
if inserting then -- add in gear
insertGear(gear, addToSlot)
else
removeGear(gear)
end
if gear ~= "empty" then gear.ZIndex = 1 end
end
function checkToolAncestry(child,parent)
if child:FindFirstChild("RobloxBuildTool") then return end -- don't show roblox build tools
if child:IsA("Tool") or child:IsA("HopperBin") then
for i = 1, #gearSlots do
if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then
if parent == nil then
gearSlots[i].Kill.Value = true
return false
elseif child.Parent == player.Character then
gearSlots[i].Selected = true
return true
elseif child.Parent == player.Backpack then
if child:IsA("Tool") then gearSlots[i].Selected = false end
return true
else
gearSlots[i].Kill.Value = true
return false
end
return true
end
end
end
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
if stuff[i]:IsA("Tool") then stuff[i].Parent = player.Backpack end
if stuff[i]:IsA("HopperBin") then
stuff[i]:Disable()
end
end
end
end
function hopperBinSwitcher(numKey, physGear)
if not physGear then return end
physGear:ToggleSelect()
if gearSlots[numKey] == "empty" then return end
if not physGear.Active then
gearSlots[numKey].Selected = false
normalizeButton(gearSlots[numKey])
else
gearSlots[numKey].Selected = true
enlargeButton(gearSlots[numKey])
end
end
function toolSwitcher(numKey)
if not gearSlots[numKey] then return end
local physGear = gearSlots[numKey].GearReference.Value
if physGear == nil then return end
removeAllEquippedGear(physGear) -- we don't remove this gear, as then we get a double switcheroo
local key = numKey
if numKey == 0 then key = 10 end
for i = 1, #gearSlots do
if gearSlots[i] and gearSlots[i] ~= "empty" and i ~= key then
normalizeButton(gearSlots[i])
gearSlots[i].Selected = false
if gearSlots[i].GearReference and gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value:IsA("HopperBin") and gearSlots[i].GearReference.Value.Active then
gearSlots[i].GearReference.Value:ToggleSelect()
end
end
end
if physGear:IsA("HopperBin") then
hopperBinSwitcher(numKey,physGear)
else
if physGear.Parent == player.Character then
physGear.Parent = player.Backpack
gearSlots[numKey].Selected = false
normalizeButton(gearSlots[numKey])
else
physGear.Parent = player.Character
gearSlots[numKey].Selected = true
enlargeButton(gearSlots[numKey])
end
end
end
function activateGear(num)
local numKey = nil
if num == "0" then
numKey = 10 -- why do lua indexes have to start at 1? :(
else
numKey = tonumber(num)
end
if(numKey == nil) then return end
if gearSlots[numKey] ~= "empty" then
toolSwitcher(numKey)
end
end
enlargeButton = function(button)
if button.Size.Y.Scale > 1 then return end
if not button.Parent then return end
if not button.Selected then return end
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then break end
if gearSlots[i] ~= button then
normalizeButton(gearSlots[i])
end
end
if not enlargeOverride then
waitingOnEnlarge = button
return
end
if button:IsA("ImageButton") or button:IsA("TextButton") then
button.ZIndex = 2
local centerizeX = -(buttonSizeEnlarge.X.Scale - button.Size.X.Scale)/2
local centerizeY = -(buttonSizeEnlarge.Y.Scale - button.Size.Y.Scale)/2
button:TweenSizeAndPosition(buttonSizeEnlarge,
UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/5,enlargeOverride)
end
end
normalizeAllButtons = function()
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then break end
if gearSlots[i] ~= button then
normalizeButton(gearSlots[i],0.1)
end
end
end
normalizeButton = function(button, speed)
if not button then return end
if button.Size.Y.Scale <= 1 then return end
if button.Selected then return end
if not button.Parent then return end
local moveSpeed = speed
if moveSpeed == nil or type(moveSpeed) ~= "number" then moveSpeed = guiTweenSpeed/5 end
if button:IsA("ImageButton") or button:IsA("TextButton") then
button.ZIndex = 1
local inverseEnlarge = 1/enlargeFactor
local centerizeX = -(buttonSizeNormal.X.Scale - button.Size.X.Scale)/2
local centerizeY = -(buttonSizeNormal.Y.Scale - button.Size.Y.Scale)/2
button:TweenSizeAndPosition(buttonSizeNormal,
UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quad,moveSpeed,enlargeOverride)
end
end
waitForDebounce = function()
if debounce.Value then
debounce.Changed:wait()
end
end
function pointInRectangle(point,rectTopLeft,rectSize)
if point.x > rectTopLeft.x and point.x < (rectTopLeft.x + rectSize.x) then
if point.y > rectTopLeft.y and point.y < (rectTopLeft.y + rectSize.y) then
return true
end
end
return false
end
function swapGear(gearClone,toFrame)
local toFrameChildren = toFrame:GetChildren()
if #toFrameChildren == 1 then
if toFrameChildren[1]:FindFirstChild("SlotNumber") then
local toSlot = tonumber(toFrameChildren[1].SlotNumber.Text)
local gearCloneSlot = tonumber(gearClone.SlotNumber.Text)
if toSlot == 0 then toSlot = 10 end
if gearCloneSlot == 0 then gearCloneSlot = 10 end
gearSlots[toSlot] = gearClone
gearSlots[gearCloneSlot] = toFrameChildren[1]
toFrameChildren[1].SlotNumber.Text = gearClone.SlotNumber.Text
toFrameChildren[1].SlotNumberDownShadow.Text = gearClone.SlotNumber.Text
toFrameChildren[1].SlotNumberUpShadow.Text = gearClone.SlotNumber.Text
local subString = string.sub(toFrame.Name,5)
gearClone.SlotNumber.Text = subString
gearClone.SlotNumberDownShadow.Text = subString
gearClone.SlotNumberUpShadow.Text = subString
gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0)
toFrameChildren[1].Position = UDim2.new(toFrameChildren[1].Position.X.Scale,0,toFrameChildren[1].Position.Y.Scale,0)
toFrameChildren[1].Parent = gearClone.Parent
gearClone.Parent = toFrame
end
else
local slotNum = tonumber(gearClone.SlotNumber.Text)
if slotNum == 0 then slotNum = 10 end
gearSlots[slotNum] = "empty" -- reset this gear slot
local subString = string.sub(toFrame.Name,5)
gearClone.SlotNumber.Text = subString
gearClone.SlotNumberDownShadow.Text = subString
gearClone.SlotNumberUpShadow.Text = subString
local toSlotNum = tonumber(gearClone.SlotNumber.Text)
if toSlotNum == 0 then toSlotNum = 10 end
gearSlots[toSlotNum] = gearClone
gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0)
gearClone.Parent = toFrame
end
end
function resolveDrag(gearClone,x,y)
local mousePoint = Vector2.new(x,y)
local frame = gearClone.Parent
local frames = frame.Parent:GetChildren()
for i = 1, #frames do
if frames[i]:IsA("Frame") then
if pointInRectangle(mousePoint, frames[i].AbsolutePosition,frames[i].AbsoluteSize) then
swapGear(gearClone,frames[i])
saveGearPositions()
return true
end
end
end
if x < frame.AbsolutePosition.x or x > ( frame.AbsolutePosition.x + frame.AbsoluteSize.x ) then
reorganizeLoadout(gearClone,false)
saveGearPositions()
return false
elseif y < frame.AbsolutePosition.y or y > ( frame.AbsolutePosition.y + frame.AbsoluteSize.y ) then
reorganizeLoadout(gearClone,false)
saveGearPositions()
return false
else
if dragBeginPos then gearClone.Position = dragBeginPos end
return -1
end
end
function saveGearPositions()
lastLoadout = {}
for i = 1, #gearSlots do
if gearSlots[i] and gearSlots[i] ~= "empty" then
lastLoadout[i] = gearSlots[i]
end
end
end
function unequipAllItems(dontEquipThis)
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then break end
if gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value ~= dontEquipThis then
if gearSlots[i].GearReference.Value:IsA("HopperBin") then
gearSlots[i].GearReference.Value:Disable()
elseif gearSlots[i].GearReference.Value:IsA("Tool") then
gearSlots[i].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack
end
gearSlots[i].Selected = false
end
end
end
function showToolTip(button, tip)
if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then
button.ToolTipLabel.Text = tostring(tip)
local xSize = button.ToolTipLabel.TextBounds.X + 6
button.ToolTipLabel.Size = UDim2.new(0,xSize,0,20)
button.ToolTipLabel.Position = UDim2.new(0.5,-xSize/2,0,-30)
button.ToolTipLabel.Visible = true
end
end
function hideToolTip(button, tip)
if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then
button.ToolTipLabel.Visible = false
end
end
local addingPlayerChild = function(child, equipped, addToSlot, inventoryGearButton)
waitForDebounce()
debounce.Value = true
if child:FindFirstChild("RobloxBuildTool") then debounce.Value = false return end -- don't show roblox build tools
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
debounce.Value = false
return -- we don't care about anything besides tools (sigh...)
end
end
if not addToSlot then
for i = 1, #gearSlots do
if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then -- we already have gear, do nothing
debounce.Value = false
return
end
end
end
local gearClone = currentLoadout.TempSlot:clone()
gearClone.Name = child.Name
gearClone.GearImage.Image = child.TextureId
if gearClone.GearImage.Image == "" then
gearClone.GearText.Text = child.Name
end
gearClone.GearReference.Value = child
gearClone.MouseEnter:connect(function()
if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then
showToolTip(gearClone, gearClone.GearReference.Value.ToolTip)
end
end)
gearClone.MouseLeave:connect(function()
if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then
hideToolTip(gearClone, gearClone.GearReference.Value.ToolTip)
end
end)
local slotToMod = -1
if not addToSlot then
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then
slotToMod = i
break
end
end
else
slotToMod = addToSlot
end
if slotToMod == - 1 then debounce.Value = false return end -- No available slot to add in!
local slotNum = slotToMod % 10
local parent = currentLoadout:FindFirstChild("Slot"..tostring(slotNum))
gearClone.Parent = parent
if inventoryGearButton then
local absolutePositionFinal = inventoryGearButton.AbsolutePosition
local currentAbsolutePosition = gearClone.AbsolutePosition
local diff = absolutePositionFinal - currentAbsolutePosition
gearClone.Position = UDim2.new(gearClone.Position.X.Scale,diff.x,gearClone.Position.Y.Scale,diff.y)
gearClone.ZIndex = 4
end
if addToSlot then
reorganizeLoadout(gearClone, true, equipped, addToSlot)
else
reorganizeLoadout(gearClone, true)
end
if gearClone.Parent == nil then debounce.Value = false return end -- couldn't fit in (hopper is full!)
if equipped then
gearClone.Selected = true
unequipAllItems(child)
delay(guiTweenSpeed + 0.01,function() -- if our gear is equipped, we will want to enlarge it when done moving
if gearClone:FindFirstChild("GearReference") and ( (gearClone.GearReference.Value:IsA("Tool") and gearClone.GearReference.Value.Parent == player.Character) or
(gearClone.GearReference.Value:IsA("HopperBin") and gearClone.GearReference.Value.Active == true) ) then
enlargeButton(gearClone)
end
end)
end
local dragBeginPos = nil
local clickCon, buttonDeleteCon, mouseEnterCon, mouseLeaveCon, dragStop, dragBegin = nil
clickCon = gearClone.MouseButton1Click:connect(function() if not gearClone.Draggable then activateGear(gearClone.SlotNumber.Text) end end)
mouseEnterCon = gearClone.MouseEnter:connect(function()
if guiBackpack.Visible then
gearClone.Draggable = true
end
end)
dragBegin = gearClone.DragBegin:connect(function(pos)
dragBeginPos = pos
gearClone.ZIndex = 7
local children = gearClone:GetChildren()
for i = 1, #children do
if children[i]:IsA("TextLabel") then
if string.find(children[i].Name,"Shadow") then
children[i].ZIndex = 8
else
children[i].ZIndex = 9
end
elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then
children[i].ZIndex = 7
end
end
end)
dragStop = gearClone.DragStopped:connect(function(x,y)
if gearClone.Selected then
gearClone.ZIndex = 2
else
gearClone.ZIndex = 1
end
local children = gearClone:GetChildren()
for i = 1, #children do
if children[i]:IsA("TextLabel") then
if string.find(children[i].Name,"Shadow") then
children[i].ZIndex = 3
else
children[i].ZIndex = 4
end
elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then
children[i].ZIndex = 2
end
end
resolveDrag(gearClone,x,y)
end)
mouseLeaveCon = gearClone.MouseLeave:connect(function()
gearClone.Draggable = false
end)
buttonDeleteCon = gearClone.AncestryChanged:connect(function()
if gearClone.Parent and gearClone.Parent.Parent == currentLoadout then return end
if clickCon then clickCon:disconnect() end
if buttonDeleteCon then buttonDeleteCon:disconnect() end
if mouseEnterCon then mouseEnterCon:disconnect() end
if mouseLeaveCon then mouseLeaveCon:disconnect() end
if dragStop then dragStop:disconnect() end
if dragBegin then dragBegin:disconnect() end
end) -- this probably isn't necessary since objects are being deleted (probably), but this might still leak just in case
local childCon = nil
local childChangeCon = nil
childCon = child.AncestryChanged:connect(function(newChild,parent)
if not checkToolAncestry(newChild,parent) then
if childCon then childCon:disconnect() end
if childChangeCon then childChangeCon:disconnect() end
removeFromInventory(child)
elseif parent == game.Players.LocalPlayer.Backpack then
normalizeButton(gearClone)
end
end)
childChangeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if gearClone and gearClone.GearImage.Image == "" then
gearClone.GearText.Text = child.Name
end
end
end)
debounce.Value = false
end
function addToInventory(child)
if not child:IsA("Tool") or not child:IsA("HopperBin") then return end
local slot = nil
for i = 1, #inventory do
if inventory[i] and inventory[i] == child then return end
if not inventory[i] then slot = i end
end
if slot then
inventory[slot] = child
elseif #inventory < 1 then
inventory[1] = child
else
inventory[#inventory + 1] = child
end
end
function removeFromInventory(child)
for i = 1, #inventory do
if inventory[i] == child then
table.remove(inventory,i)
inventory[i] = nil
end
end
end
-- these next two functions are used for safe guarding
-- when we are waiting for character to come back after dying
function activateLoadout()
keyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) activateGear(key) end)
currentLoadout.Visible = true
end
function deactivateLoadout()
if keyPressCon then keyPressCon:disconnect() end
currentLoadout.Visible = false
end
function setupBackpackListener()
if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end
backpackChildCon = player.Backpack.ChildAdded:connect(function(child)
addingPlayerChild(child)
addToInventory(child)
-- now store info in case of death
saveGearPositions()
end)
end
function playerCharacterChildAdded(child)
addingPlayerChild(child,true)
addToInventory(child)
-- now store info in case of death
saveGearPositions()
end
-- End Functions
-- Begin Script
wait() -- let stuff initialize incase this is first heartbeat...
waitForChild(player,"Backpack")
local backpackChildren = player.Backpack:GetChildren()
local size = math.min(10,#backpackChildren)
for i = 1, size do
addingPlayerChild(backpackChildren[i],false)
-- now store info in case of death
saveGearPositions()
end
setupBackpackListener()
waitForProperty(player,"Character")
for i,v in ipairs(player.Character:GetChildren()) do
playerCharacterChildAdded(v)
end
characterChildAddedCon = player.Character.ChildAdded:connect(function(child) playerCharacterChildAdded(child) end)
waitForChild(player.Character,"Humanoid")
humanoidDiedCon = player.Character.Humanoid.Died:connect(function()
if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end
deactivateLoadout()
if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end
end)
player.CharacterRemoving:connect(function()
for i = 1, #gearSlots do
if gearSlots[i] ~= "empty" then
gearSlots[i].Parent = nil
gearSlots[i] = "empty"
end
end
end)
player.CharacterAdded:connect(function()
player = game.Players.LocalPlayer -- make sure we are still looking at the correct character
waitForChild(player,"Backpack")
local backpackChildren = player.Backpack:GetChildren()
-- Make sure we put gear back in where we last had them
for i = 1, #backpackChildren do
for pos,v in pairs(lastLoadout) do
if v["Name"] and v.Name == backpackChildren[i].Name then
addingPlayerChild(backpackChildren[i],false,pos)
lastLoadout[pos] = nil
break
end
end
end
setupBackpackListener()
if characterChildAddedCon then
characterChildAddedCon:disconnect()
characterChildAddedCon = nil
end
characterChildAddedCon =
player.Character.ChildAdded:connect(function(child)
addingPlayerChild(child,true)
-- now store info in case of death
saveGearPositions()
end)
waitForChild(player.Character,"Humanoid")
humanoidDiedCon =
player.Character.Humanoid.Died:connect(function()
deactivateLoadout()
if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end
if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end
end)
activateLoadout()
end)
waitForChild(guiBackpack,"SwapSlot")
guiBackpack.SwapSlot.Changed:connect(function()
if guiBackpack.SwapSlot.Value then
local swapSlot = guiBackpack.SwapSlot
local pos = swapSlot.Slot.Value
if pos == 0 then pos = 10 end
if gearSlots[pos] then
reorganizeLoadout(gearSlots[pos],false)
end
if swapSlot.GearButton.Value then
addingPlayerChild(swapSlot.GearButton.Value.GearReference.Value,false,pos)
-- now store info in case of death
saveGearPositions()
end
guiBackpack.SwapSlot.Value = false
end
end)
keyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) activateGear(key) end)
-
Dialogs
-
false
4288914085
1
4279970357
1
false
false
ControlFrame
0
0
0
0
1
0
1
0
0
0
true
1
-
false
4288914085
1
4279970357
1
false
false
BottomLeftControl
0
0
1
-46
0
130
0
46
0
0
true
1
-
false
4288914085
1
4279970357
1
false
false
NotificationBox
1
-200
0.5
0
0
200
0.419999987
0
0
true
1
-
false
Init
--rbxsig%XeVmMtUuu+dXh8pEbcaTkr2m9RJZXY42LaACJ12YYcuPtOUxy4Azi8uMDGU8ZTh7cvZC9BlOWgqmZHKjESSdfOZl0/cgd2JKHPZ2UqiqA1slJa7R5GtCcGXlNPHW8KDYgJGRuwe8h5CSiMDOl6QLTSEegTOG7fzHk/n1AFcRN8I=%
--rbxassetid%39250920%
--fixed by Carrot#0559
function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
local beter = game.Lighting
function waitForDialogChildrenMyLord(beter, name)
while not beter:FindFirstChild(name) do
beter.ChildAdded:wait()
end
end
local bois = game.Players.LocalPlayer.PlayerGui
function waitForFaker(bois, name)
while not bois:FindFirstChild(name) do
bois.ChildAdded:wait()
end
end
local mainFrame
local choices = {}
local lastChoice
local choiceMap = {}
local currentConversationDialog
local currentConversationPartner
local currentAbortDialogScript
local tooFarAwayMessage = "You are too far away to chat!"
local tooFarAwaySize = 300
local characterWanderedOffMessage = "Chat ended because you walked away"
local characterWanderedOffSize = 350
local conversationTimedOut = "Chat ended because you didn't reply"
local conversationTimedOutSize = 350
local player
local screenGui
local chatNotificationGui
local messageDialog
local timeoutScript = game.Lighting.ReenableDialogScript
local reenableDialogScript = game.Lighting.TimeoutScript
local dialogMap = {}
local dialogConnections = {}
local gui = nil
--waitForDialogChildrenMyLord(game,"CoreGui")
--waitForDialogChildrenMyLord(game.CoreGui,"RobloxGui")
--if game.CoreGui.RobloxGui:FindFirstChild("ControlFrame") then
-- gui = game.CoreGui.RobloxGui.ControlFrame
--else
-- gui = game.CoreGui.RobloxGui
--end
function currentTone()
if currentConversationDialog then
return currentConversationDialog.Tone
else
return Enum.DialogTone.Neutral
end
end
function createChatNotificationGui()
chatNotificationGui = Instance.new("BillboardGui")
chatNotificationGui.Name = "ChatNotificationGui"
chatNotificationGui.ExtentsOffset = Vector3.new(0,1,0)
chatNotificationGui.Size = UDim2.new(4, 0, 5.42857122, 0)
chatNotificationGui.SizeOffset = Vector2.new(0,0)
chatNotificationGui.StudsOffset = Vector3.new(0.4, 4.3, 0)
chatNotificationGui.Enabled = true
chatNotificationGui.Active = true
local image = Instance.new("ImageLabel")
image.Name = "Image"
image.Active = false
image.BackgroundTransparency = 1
image.Position = UDim2.new(0,0,0,0)
image.Size = UDim2.new(1.0,0,1.0,0)
image.Image = ""
image.Parent = chatNotificationGui
local button = Instance.new("ImageButton")
button.Name = "Button"
button.AutoButtonColor = false
button.Position = UDim2.new(0.0879999995, 0, 0.0529999994, 0)
button.Size = UDim2.new(0.829999983, 0, 0.460000008, 0)
button.Image = ""
button.BackgroundTransparency = 1
button.Parent = image
end
function getChatColor(tone)
if tone == Enum.DialogTone.Neutral then
return Enum.ChatColor.Blue
elseif tone == Enum.DialogTone.Friendly then
return Enum.ChatColor.Green
elseif tone == Enum.DialogTone.Enemy then
return Enum.ChatColor.Red
end
end
function styleChoices(tone)
for i, obj in pairs(choices) do
resetColor(obj, tone)
end
resetColor(lastChoice, tone)
end
function styleMainFrame(tone)
if tone == Enum.DialogTone.Neutral then
mainFrame.Style = Enum.FrameStyle.ChatBlue
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png"
elseif tone == Enum.DialogTone.Friendly then
mainFrame.Style = Enum.FrameStyle.ChatGreen
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botGreen_tailRight.png"
elseif tone == Enum.DialogTone.Enemy then
mainFrame.Style = Enum.FrameStyle.ChatRed
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botRed_tailRight.png"
end
styleChoices(tone)
end
function setChatNotificationTone(gui, purpose, tone)
if tone == Enum.DialogTone.Neutral then
gui.Image.Image = "rbxasset://textures/chatBubble_botBlue_notify_bkg.png"
elseif tone == Enum.DialogTone.Friendly then
gui.Image.Image = "rbxasset://textures/chatBubble_botGreen_notify_bkg.png"
elseif tone == Enum.DialogTone.Enemy then
gui.Image.Image = "rbxasset://textures/chatBubble_botRed_notify_bkg.png"
end
if purpose == Enum.DialogPurpose.Quest then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_bang.png"
elseif purpose == Enum.DialogPurpose.Help then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_question.png"
elseif purpose == Enum.DialogPurpose.Shop then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_money.png"
end
end
function createMessageDialog()
messageDialog = Instance.new("Frame");
messageDialog.Name = "DialogScriptMessage"
messageDialog.Style = Enum.FrameStyle.RobloxRound
messageDialog.Visible = false
local text = Instance.new("TextLabel")
text.Name = "Text"
text.Position = UDim2.new(0,0,0,-1)
text.Size = UDim2.new(1,0,1,0)
text.FontSize = Enum.FontSize.Size14
text.BackgroundTransparency = 1
text.TextColor3 = Color3.new(1,1,1)
text.Parent = messageDialog
end
function showMessage(msg, size)
messageDialog.Text.Text = msg
messageDialog.Size = UDim2.new(0,size,0,40)
messageDialog.Position = UDim2.new(0.5, -size/2, 0.5, -40)
messageDialog.Visible = true
wait(2)
messageDialog.Visible = false
end
function variableDelay(str)
local length = math.min(string.len(str), 100)
wait(0.75 + ((length/75) * 1.5))
end
function resetColor(frame, tone)
if tone == Enum.DialogTone.Neutral then
frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255)
frame.Number.TextColor3 = Color3.new(45/255, 142/255, 245/255)
elseif tone == Enum.DialogTone.Friendly then
frame.BackgroundColor3 = Color3.new(0/255, 77/255, 0/255)
frame.Number.TextColor3 = Color3.new(0/255, 190/255, 0/255)
elseif tone == Enum.DialogTone.Enemy then
frame.BackgroundColor3 = Color3.new(140/255, 0/255, 0/255)
frame.Number.TextColor3 = Color3.new(255/255,88/255, 79/255)
end
end
function highlightColor(frame, tone)
if tone == Enum.DialogTone.Neutral then
frame.BackgroundColor3 = Color3.new(2/255, 108/255, 255/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
elseif tone == Enum.DialogTone.Friendly then
frame.BackgroundColor3 = Color3.new(0/255, 128/255, 0/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
elseif tone == Enum.DialogTone.Enemy then
frame.BackgroundColor3 = Color3.new(204/255, 0/255, 0/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
end
end
function wanderDialog()
print("Wander")
mainFrame.Visible = false
endDialog()
showMessage(characterWanderedOffMessage, characterWanderedOffSize)
end
function timeoutDialog()
print("Timeout")
mainFrame.Visible = false
endDialog()
showMessage(conversationTimedOut, conversationTimedOutSize)
end
function normalEndDialog()
print("Done")
endDialog()
end
function endDialog()
if currentAbortDialogScript then
currentAbortDialogScript:Remove()
currentAbortDialogScript = nil
end
local dialog = currentConversationDialog
currentConversationDialog = nil
if dialog and dialog.InUse then
local reenableScript = reenableDialogScript:Clone()
reenableScript.archivable = false
reenableScript.Disabled = false
reenableScript.Parent = dialog
end
for dialog, gui in pairs(dialogMap) do
if dialog and gui then
gui.Enabled = not dialog.InUse
end
end
currentConversationPartner = nil
end
function sanitizeMessage(msg)
if string.len(msg) == 0 then
return "..."
else
return msg
end
end
function selectChoice(choice)
renewKillswitch(currentConversationDialog)
--First hide the Gui
mainFrame.Visible = false
if choice == lastChoice then
game.Chat:Chat(game.Players.LocalPlayer.Character, "Goodbye!", getChatColor(currentTone()))
normalEndDialog()
else
local dialogChoice = choiceMap[choice]
game.Chat:Chat(game.Players.LocalPlayer.Character, sanitizeMessage(dialogChoice.UserDialog), getChatColor(currentTone()))
wait(1)
--currentConversationDialog:SignalDialogChoiceSelected(player, dialogChoice)
game.Chat:Chat(currentConversationPartner, sanitizeMessage(dialogChoice.ResponseDialog), getChatColor(currentTone()))
variableDelay(dialogChoice.ResponseDialog)
presentDialogChoices(currentConversationPartner, dialogChoice:GetChildren())
end
end
function newChoice(numberText)
local frame = Instance.new("TextButton")
frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255)
frame.AutoButtonColor = false
frame.BorderSizePixel = 0
frame.Text = ""
frame.MouseEnter:connect(function() highlightColor(frame, currentTone()) end)
frame.MouseLeave:connect(function() resetColor(frame, currentTone()) end)
frame.MouseButton1Click:connect(function() selectChoice(frame) end)
local number = Instance.new("TextLabel")
number.Name = "Number"
number.TextColor3 = Color3.new(127/255, 212/255, 255/255)
number.Text = numberText
number.FontSize = Enum.FontSize.Size14
number.BackgroundTransparency = 1
number.Position = UDim2.new(0,4,0,2)
number.Size = UDim2.new(0,20,0,24)
number.TextXAlignment = Enum.TextXAlignment.Left
number.TextYAlignment = Enum.TextYAlignment.Top
number.Parent = frame
local prompt = Instance.new("TextLabel")
prompt.Name = "UserPrompt"
prompt.BackgroundTransparency = 1
prompt.TextColor3 = Color3.new(1,1,1)
prompt.FontSize = Enum.FontSize.Size14
prompt.Position = UDim2.new(0,28, 0, 2)
prompt.Size = UDim2.new(1,-32, 1, -4)
prompt.TextXAlignment = Enum.TextXAlignment.Left
prompt.TextYAlignment = Enum.TextYAlignment.Top
prompt.TextWrap = true
prompt.Parent = frame
return frame
end
function initialize(parent)
choices[1] = newChoice("1)")
choices[2] = newChoice("2)")
choices[3] = newChoice("3)")
choices[4] = newChoice("4)")
lastChoice = newChoice("5)")
lastChoice.UserPrompt.Text = "Goodbye!"
lastChoice.Size = UDim2.new(1,0,0,28)
mainFrame = Instance.new("Frame")
mainFrame.Name = "UserDialogArea"
mainFrame.Size = UDim2.new(0, 350, 0, 200)
mainFrame.Style = Enum.FrameStyle.ChatBlue
mainFrame.Visible = false
local imageLabel = Instance.new("ImageLabel")
imageLabel.Name = "Tail"
imageLabel.Size = UDim2.new(0,62,0,53)
imageLabel.Position = UDim2.new(1,8,0.25)
imageLabel.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png"
imageLabel.BackgroundTransparency = 1
imageLabel.Parent = mainFrame
for n, obj in pairs(choices) do
obj.Parent = mainFrame
end
lastChoice.Parent = mainFrame
mainFrame.Parent = parent
end
function presentDialogChoices(talkingPart, dialogChoices)
if not currentConversationDialog then
return
end
currentConversationPartner = talkingPart
local sortedDialogChoices = {}
for n, obj in pairs(dialogChoices) do
if obj:IsA("DialogChoice") then
table.insert(sortedDialogChoices, obj)
end
end
table.sort(sortedDialogChoices, function(a,b) return a.Name < b.Name end)
if #sortedDialogChoices == 0 then
normalEndDialog()
return
end
local pos = 1
local yPosition = 0
choiceMap = {}
for n, obj in pairs(choices) do
obj.Visible = false
end
for n, obj in pairs(sortedDialogChoices) do
if pos <= #choices then
--3 lines is the maximum, set it to that temporarily
choices[pos].Size = UDim2.new(1, 0, 0, 24*3)
choices[pos].UserPrompt.Text = obj.UserDialog
local height = math.ceil(choices[pos].UserPrompt.TextBounds.Y/24)*24
choices[pos].Position = UDim2.new(0, 0, 0, yPosition)
choices[pos].Size = UDim2.new(1, 0, 0, height)
choices[pos].Visible = true
choiceMap[choices[pos]] = obj
yPosition = yPosition + height
pos = pos + 1
end
end
lastChoice.Position = UDim2.new(0,0,0,yPosition)
lastChoice.Number.Text = pos .. ")"
mainFrame.Size = UDim2.new(0, 350, 0, yPosition+24+32)
mainFrame.Position = UDim2.new(0,20,0.0, -mainFrame.Size.Y.Offset-20)
styleMainFrame(currentTone())
mainFrame.Visible = true
end
function doDialog(dialog)
while not Instance.Lock(dialog, player) do
wait()
end
if dialog.InUse then
Instance.Unlock(dialog)
return
else
dialog.InUse = true
Instance.Unlock(dialog)
end
currentConversationDialog = dialog
game.Chat:Chat(dialog.Parent, dialog.InitialPrompt, getChatColor(dialog.Tone))
variableDelay(dialog.InitialPrompt)
presentDialogChoices(dialog.Parent, dialog:GetChildren())
end
function renewKillswitch(dialog)
if currentAbortDialogScript then
currentAbortDialogScript:Remove()
currentAbortDialogScript = nil
end
currentAbortDialogScript = timeoutScript:Clone()
currentAbortDialogScript.archivable = false
currentAbortDialogScript.Disabled = false
currentAbortDialogScript.Parent = dialog
end
function checkForLeaveArea()
while currentConversationDialog do
if currentConversationDialog.Parent and (player:DistanceFromCharacter(currentConversationDialog.Parent.Position) >= currentConversationDialog.ConversationDistance) then
wanderDialog()
end
wait(1)
end
end
function startDialog(dialog)
if dialog.Parent and dialog.Parent:IsA("BasePart") then
if player:DistanceFromCharacter(dialog.Parent.Position) >= dialog.ConversationDistance then
showMessage(tooFarAwayMessage, tooFarAwaySize)
return
end
for dialog, gui in pairs(dialogMap) do
if dialog and gui then
gui.Enabled = false
end
end
renewKillswitch(dialog)
delay(1, checkForLeaveArea)
doDialog(dialog)
end
end
function removeDialog(dialog)
if dialogMap[dialog] then
dialogMap[dialog]:Remove()
dialogMap[dialog] = nil
end
if dialogConnections[dialog] then
dialogConnections[dialog]:disconnect()
dialogConnections[dialog] = nil
end
end
function addDialog(dialog)
if dialog.Parent then
if dialog.Parent:IsA("BasePart") then
local chatGui = chatNotificationGui:clone()
chatGui.Enabled = not dialog.InUse
chatGui.Adornee = dialog.Parent
chatGui.Parent = game.Players.LocalPlayer.PlayerGui
chatGui.Image.Button.MouseButton1Click:connect(function() startDialog(dialog) end)
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
dialogMap[dialog] = chatGui
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
if prop == "Parent" and dialog.Parent then
--This handles the reparenting case, seperate from removal case
removeDialog(dialog)
addDialog(dialog)
elseif prop == "InUse" then
chatGui.Enabled = not currentConversationDialog and not dialog.InUse
if dialog == currentConversationDialog then
timeoutDialog()
end
elseif prop == "Tone" or prop == "Purpose" then
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
end
end)
else -- still need to listen to parent changes even if current parent is not a BasePart
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
if prop == "Parent" and dialog.Parent then
--This handles the reparenting case, seperate from removal case
removeDialog(dialog)
addDialog(dialog)
end
end)
end
end
end
--[[function fetchScripts()
local model = game:GetService("InsertService"):LoadAsset(39226062)
if type(model) == "string" then -- load failed, lets try again
wait(0.1)
model = game:GetService("InsertService"):LoadAsset(39226062)
end
if type(model) == "string" then -- not going to work, lets bail
return
end
waitForDialogChildrenMyLord(model,"TimeoutScript")
timeoutScript = model.TimeoutScript
waitForDialogChildrenMyLord(model,"ReenableDialogScript")
reenableDialogScript = model.ReenableDialogScript
end
]]--
function onLoad()
waitForProperty(game.Players, "LocalPlayer")
player = game.Players.LocalPlayer
waitForProperty(player, "Character")
--print("Fetching Scripts")
--fetchScripts()
--print("Creating Guis")
createChatNotificationGui()
waitForFaker(bois,"Dialogs")
--print("Creating MessageDialog")
createMessageDialog()
messageDialog.Parent = game.Players.LocalPlayer.PlayerGui.Dialogs
--print("Initializing Frame")
local frame = Instance.new("Frame")
frame.Name = "DialogFrame"
frame.Position = UDim2.new(0,0,0,0)
frame.Size = UDim2.new(0,0,0,0)
frame.BackgroundTransparency = 1
frame.Parent = game.Players.LocalPlayer.PlayerGui.Dialogs.ControlFrame.BottomLeftControl
initialize(frame)
--print("Adding Dialogs")
game.CollectionService.ItemAdded:connect(function(obj) if obj:IsA("Dialog") then addDialog(obj) end end)
game.CollectionService.ItemRemoved:connect(function(obj) if obj:IsA("Dialog") then removeDialog(obj) end end)
for i, obj in pairs(game.CollectionService:GetCollection("Dialog")) do
if obj:IsA("Dialog") then
addDialog(obj)
end
end
end
onLoad()
-
Health
-
false
4285215356
1
4279970357
1
false
false
tray
0.5
-44
1
-26
0
170
0
18
2
0
true
1
-
false
4294967295
1
4279970357
1
false
false
rbxasset://textures/healthgui/bkg.png
bkg
0
0
0
0
1
0
1
0
0
true
1
-
false
4294967295
1
4279970357
1
false
false
rbxasset://textures/healthgui/BarRed.png
barRed
0.0189999994
0
0.100000001
0
0
0
0
0
0
true
1
-
false
4294967295
1.00000012
4279970357
0
false
false
bar2
0.0189999994
0
0.100000001
0
0.192000002
0
0.829999983
0
0
0
true
1
-
false
Init
h = game.Players.LocalPlayer.Character.Humanoid
tray = script.Parent.Parent
base = tray.Parent
local lastHealth = 100
local lastHealth2 = 100
local maxWidth = 0.96
function UpdateGUI(health)
local width = (health / h.MaxHealth) * maxWidth
local height = 0.83
local lastX = tray.bar.Position.X.Scale
local x = 0.019 + (maxWidth - width)
local y = 0.1
tray.bar.Position = UDim2.new(x,0,y, 0)
tray.bar.Size = UDim2.new(width, 0, height, 0)
-- If more than 1/4 health, bar = green. Else, bar = red.
if( (health / h.MaxHealth) > 0.25 ) then
tray.barRed.Size = UDim2.new(0, 0, 0, 0)
else
tray.barRed.Position = tray.bar.Position
tray.barRed.Size = tray.bar.Size
tray.bar.Size = UDim2.new(0, 0, 0, 0)
end
if ( (lastHealth - health) > (h.MaxHealth / 10) ) then
lastHealth = health
if h.Health ~= h.MaxHealth then
delay(0,function()
AnimateHurtOverlay()
end)
delay(0,function()
AnimateBars(x, y, lastX, height)
end)
end
else
lastHealth = health
end
end
function AnimateBars(x, y, lastX, height)
local width = math.abs(x - lastX)
if( x > lastX ) then
x = lastX
end
tray.bar2.Position = UDim2.new(x,0, y, 0)
tray.bar2.Size = UDim2.new(width, 0, height, 0)
tray.bar2.BackgroundTransparency = 0
local GBchannels = 1
local j = 0.2
local i_total = 30
for i=1,i_total do
-- Increment Values
if (GBchannels < 0.2) then
j = -j
end
GBchannels = GBchannels + j
if (i > (i_total - 10)) then
tray.bar2.BackgroundTransparency = tray.bar2.BackgroundTransparency + 0.1
end
tray.bar2.BackgroundColor3 = Color3.new(1, GBchannels, GBchannels)
wait(0.02)
end
end
function AnimateHurtOverlay()
-- Start:
-- overlay.Position = UDim2.new(0, 0, 0, -22)
-- overlay.Size = UDim2.new(1, 0, 1.15, 30)
-- Finish:
-- overlay.Position = UDim2.new(-2, 0, -2, -22)
-- overlay.Size = UDim2.new(4.5, 0, 4.65, 30)
overlay = base.hurtOverlay
overlay.Visible = true
overlay.Position = UDim2.new(-2, 0, -2, -22)
overlay.Size = UDim2.new(4.5, 0, 4.65, 30)
-- Animate In, fast
local i_total = 2
local wiggle_total = 0
local wiggle_i = 0.02
for i=1,i_total do
overlay.Position = UDim2.new( (-2 + (2 * (i/i_total)) + wiggle_total/2), 0, (-2 + (2 * (i/i_total)) + wiggle_total/2), -22 )
overlay.Size = UDim2.new( (4.5 - (3.5 * (i/i_total)) + wiggle_total), 0, (4.65 - (3.5 * (i/i_total)) + wiggle_total), 30 )
wait(0.01)
end
i_total = 30
wait(0.03)
-- Animate Out, slow
for i=1,i_total do
if( math.abs(wiggle_total) > (wiggle_i * 3) ) then
wiggle_i = -wiggle_i
end
wiggle_total = wiggle_total + wiggle_i
overlay.Position = UDim2.new( (0 - (2 * (i/i_total)) + wiggle_total/2), 0, (0 - (2 * (i/i_total)) + wiggle_total/2), -22 )
overlay.Size = UDim2.new( (1 + (3.5 * (i/i_total)) + wiggle_total), 0, (1.15 + (3.5 * (i/i_total)) + wiggle_total), 30 )
wait(0.01)
end
-- Hide after we're done
overlay.Position = UDim2.new(10, 0, 0, 0)
overlay.Visible = false
end
h.Changed:connect(function()
UpdateGUI(h.Health)
if ( (lastHealth2 - h.Health) > (h.MaxHealth / 10) ) then
lastHealth2 = h.Health
else
lastHealth2 = h.Health
end end)
-
false
4294967295
1
4279970357
1
false
false
rbxasset://textures/healthgui/Bar.png
bar
0.0189999994
0
0.100000001
0
0.959999979
0
0.829999983
0
0
true
1
-
false
4294967295
1
4279970357
0
false
false
rbxasset://textures/healthgui/label.png
label
0.680000007
0
0.300000012
0
0.25
0
0.349999994
0
0
true
1
-
false
4290164919
1
4279970357
1
false
false
rbxasset://textures/healthgui/HurtOverlay.png
hurtOverlay
2
0
0
-22
1
0
1.1500001
30
0
false
1
-
false
Hide
while true do
game.Players.LocalPlayer.PlayerGui.HealthGUI.tray.Visible = false
game.Players.LocalPlayer.PlayerGui.HealthGUI.hurtOverlay.Visible = false
end
-
Menu
-
false
4288914085
1
4279970357
1
false
false
ControlFrame
0
0
0
0
1
0
1
0
0
0
true
1
-
false
4288914085
1
4279970357
1
false
false
BottomLeftControl
0
0
1
-46
0
130
0
46
0
0
true
1
-
true
true
4288914085
1
4279970357
1
false
false
rbxasset://textures/Exit.png
false
Exit
0
2
0
-2
false
0
56
0
41
0
0
false
1
-
false
4288914085
1
4279970357
1
false
false
BottomRightControl
1
-180
1
-41
0
180
0
41
0
0
true
1
-
false
4288914085
1
4279970357
1
false
false
TopLeftControl
0
0
0
0
0.0500000007
0
0.0500000007
0
0
0
true
1
-
false
4288914085
1
4279970357
1
false
false
NotificationBox
1
-200
0.5
0
0
200
0.419999987
0
0
true
1
-
false
Workaround
game.Players.LocalPlayer.PlayerGui.Menu.MenuScript.Disabled = true
game.Players.LocalPlayer.PlayerGui.Menu.MenuScript.Disabled = false
-
false
MenuScript
-- fixed by iago#6808 --
-- version 0.25 --
-- changelog: --
-- 100% finished settings menu --
-- report abuse is still in work --
local t = {}
local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
local eventConnection = nil
--Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
local tryConnect = function()
if game:IsAncestorOf(parentInstance) then
--Entering the world, make sure we are connected/synced
if not eventConnection then
eventConnection = instance[event]:connect(signalFunc)
if syncFunc then syncFunc() end
end
else
--Probably leaving the world, so disconnect for now
if eventConnection then
eventConnection:disconnect()
if removeFunc then removeFunc() end
end
end
end
--Hook it up to ancestryChanged signal
local connection = parentInstance.AncestryChanged:connect(tryConnect)
--Now connect us if we're already in the world
tryConnect()
return connection
end
local function getScreenGuiAncestor(instance)
local localInstance = instance
while localInstance and not localInstance:IsA("ScreenGui") do
localInstance = localInstance.Parent
end
return localInstance
end
local function CreateButtons(frame, buttons, yPos, ySize)
local buttonNum = 1
local buttonObjs = {}
for i, obj in ipairs(buttons) do
local button = Instance.new("TextButton")
button.Name = "Button" .. buttonNum
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size18
button.AutoButtonColor = true
button.Modal = true
if obj["Style"] then
button.Style = obj.Style
else
button.Style = Enum.ButtonStyle.RobloxButton
end
if obj["ZIndex"] then
button.ZIndex = obj.ZIndex
end
button.Text = obj.Text
button.TextColor3 = Color3.new(1,1,1)
button.MouseButton1Click:connect(obj.Function)
button.Parent = frame
buttonObjs[buttonNum] = button
buttonNum = buttonNum + 1
end
local numButtons = buttonNum-1
if numButtons == 1 then
frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
elseif numButtons == 2 then
frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
elseif numButtons >= 3 then
local spacing = .1 / numButtons
local buttonSize = .9 / numButtons
buttonNum = 1
while buttonNum <= numButtons do
buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
buttonNum = buttonNum + 1
end
end
end
local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
local steps = 10
local newStep = steps - 1 --otherwise we really get one more step than we want
local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
local wholeNum, remainder = math.modf(relativePosX * newStep)
if remainder > 0.5 then
wholeNum = wholeNum + 1
end
relativePosX = wholeNum/newStep
local result = math.ceil(relativePosX * newStep)
if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
sliderPosition.Value = result + 1
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end
end
local function cancelSlide(areaSoak)
areaSoak.Visible = false
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
end
t.CreateStyledMessageDialog = function(title, message, style, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0, 165)
frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local styleImage = Instance.new("ImageLabel")
styleImage.Name = "StyleImage"
styleImage.BackgroundTransparency = 1
styleImage.Position = UDim2.new(0,5,0,15)
if style == "error" or style == "Error" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42565285"
elseif style == "notify" or style == "Notify" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42604978"
elseif style == "confirm" or style == "Confirm" then
styleImage.Size = UDim2.new(0, 74, 0, 76)
styleImage.Image = "http://www.roblox.com/asset/?id=42557901"
else
return t.CreateMessageDialog(title,message,buttons)
end
styleImage.Parent = frame
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.TextStrokeTransparency = 0
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 80, 0, 0)
titleLabel.Size = UDim2.new(1, -80, 0, 40)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextStrokeTransparency = 0
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
return frame
end
t.CreateMessageDialog = function(title, message, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0.5, 0)
frame.Position = UDim2.new(0.25, 0, 0.25, 0)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 0, 0, 0)
titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
return frame
end
t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ)
local baseZIndex = 0
if (type(baseZ) == "number") then
baseZIndex = baseZ
end
local width = UDim.new(0, 100)
local height = UDim.new(0, 32)
local xPos = 0.055
local frame = Instance.new("Frame")
local textColor = Color3.new(1,1,1)
if (whiteSkin) then
textColor = Color3.new(0.5, 0.5, 0.5)
end
frame.Name = "DropDownMenu"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(width, height)
local dropDownMenu = Instance.new("TextButton")
dropDownMenu.Name = "DropDownMenuButton"
dropDownMenu.TextWrap = true
dropDownMenu.TextColor3 = textColor
dropDownMenu.Text = "Choose One"
dropDownMenu.Font = Enum.Font.ArialBold
dropDownMenu.FontSize = Enum.FontSize.Size18
dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
dropDownMenu.BackgroundTransparency = 1
dropDownMenu.AutoButtonColor = true
if (whiteSkin) then
dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
dropDownMenu.Size = UDim2.new(1,0,1,0)
dropDownMenu.Parent = frame
dropDownMenu.ZIndex = 2 + baseZIndex
local dropDownIcon = Instance.new("ImageLabel")
dropDownIcon.Name = "Icon"
dropDownIcon.Active = false
if (whiteSkin) then
dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png"
dropDownIcon.Size = UDim2.new(0,16,0,12)
dropDownIcon.Position = UDim2.new(1,-17,0.5, -6)
else
dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894"
dropDownIcon.Size = UDim2.new(0,11,0,6)
dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
end
dropDownIcon.BackgroundTransparency = 1
dropDownIcon.Parent = dropDownMenu
dropDownIcon.ZIndex = 2 + baseZIndex
local itemCount = #items
local dropDownItemCount = #items
local useScrollButtons = false
if dropDownItemCount > 6 then
useScrollButtons = true
dropDownItemCount = 6
end
local droppedDownMenu = Instance.new("TextButton")
droppedDownMenu.Name = "List"
droppedDownMenu.Text = ""
droppedDownMenu.BackgroundTransparency = 1
--droppedDownMenu.AutoButtonColor = true
if (whiteSkin) then
droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
droppedDownMenu.Visible = false
droppedDownMenu.Active = true --Blocks clicks
droppedDownMenu.Position = UDim2.new(0,0,0,0)
droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
droppedDownMenu.Parent = frame
droppedDownMenu.ZIndex = 2 + baseZIndex
local choiceButton = Instance.new("TextButton")
choiceButton.Name = "ChoiceButton"
choiceButton.BackgroundTransparency = 1
choiceButton.BorderSizePixel = 0
choiceButton.Text = "ReplaceMe"
choiceButton.TextColor3 = textColor
choiceButton.TextXAlignment = Enum.TextXAlignment.Left
choiceButton.TextYAlignment = Enum.TextYAlignment.Center
choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
choiceButton.Font = Enum.Font.Arial
choiceButton.FontSize = Enum.FontSize.Size18
if useScrollButtons then
choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
else
choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
end
choiceButton.TextWrap = true
choiceButton.ZIndex = 2 + baseZIndex
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = true
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 3 + baseZIndex
local dropDownSelected = false
local scrollUpButton
local scrollDownButton
local scrollMouseCount = 0
local setZIndex = function(baseZIndex)
droppedDownMenu.ZIndex = baseZIndex +1
if scrollUpButton then
scrollUpButton.ZIndex = baseZIndex + 3
end
if scrollDownButton then
scrollDownButton.ZIndex = baseZIndex + 3
end
local children = droppedDownMenu:GetChildren()
if children then
for i, child in ipairs(children) do
if child.Name == "ChoiceButton" then
child.ZIndex = baseZIndex + 2
elseif child.Name == "ClickCaptureButton" then
child.ZIndex = baseZIndex
end
end
end
end
local scrollBarPosition = 1
local updateScroll = function()
if scrollUpButton then
scrollUpButton.Active = scrollBarPosition > 1
end
if scrollDownButton then
scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
end
local children = droppedDownMenu:GetChildren()
if not children then return end
local childNum = 1
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
obj.Visible = false
else
obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
obj.Visible = true
end
obj.TextColor3 = textColor
obj.BackgroundTransparency = 1
childNum = childNum + 1
end
end
end
local toggleVisibility = function()
dropDownSelected = not dropDownSelected
areaSoak.Visible = not areaSoak.Visible
dropDownMenu.Visible = not dropDownSelected
droppedDownMenu.Visible = dropDownSelected
if dropDownSelected then
setZIndex(4 + baseZIndex)
else
setZIndex(2 + baseZIndex)
end
if useScrollButtons then
updateScroll()
end
end
droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
local updateSelection = function(text)
local foundItem = false
local children = droppedDownMenu:GetChildren()
local childNum = 1
if children then
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if obj.Text == text then
obj.Font = Enum.Font.ArialBold
foundItem = true
scrollBarPosition = childNum
if (whiteSkin) then
obj.TextColor3 = Color3.new(90/255,142/255,233/255)
end
else
obj.Font = Enum.Font.Arial
if (whiteSkin) then
obj.TextColor3 = textColor
end
end
childNum = childNum + 1
end
end
end
if not text then
dropDownMenu.Text = "Choose One"
scrollBarPosition = 1
else
if not foundItem then
error("Invalid Selection Update -- " .. text)
end
if scrollBarPosition + dropDownItemCount > itemCount + 1 then
scrollBarPosition = itemCount - dropDownItemCount + 1
end
dropDownMenu.Text = text
end
end
local function scrollDown()
if scrollBarPosition + dropDownItemCount <= itemCount then
scrollBarPosition = scrollBarPosition + 1
updateScroll()
return true
end
return false
end
local function scrollUp()
if scrollBarPosition > 1 then
scrollBarPosition = scrollBarPosition - 1
updateScroll()
return true
end
return false
end
if useScrollButtons then
--Make some scroll buttons
scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
scrollUpButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollUp()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollUp() == false then
break
end
wait(0.1)
end
end)
scrollUpButton.Parent = droppedDownMenu
scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
scrollDownButton.Position = UDim2.new(1,-11,1,-11)
scrollDownButton.Parent = droppedDownMenu
scrollDownButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollDown()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollDown() == false then
break
end
wait(0.1)
end
end)
local scrollbar = Instance.new("ImageLabel")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
scrollbar.Parent = droppedDownMenu
end
for i,item in ipairs(items) do
-- needed to maintain local scope for items in event listeners below
local button = choiceButton:clone()
if forRoblox then
end
button.Text = item
button.Parent = droppedDownMenu
if (whiteSkin) then
button.TextColor3 = textColor
end
button.MouseButton1Click:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
updateSelection(item)
onSelect(item)
toggleVisibility()
end)
button.MouseEnter:connect(function()
--Add Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(0,0,0)
end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
end)
end
--This does the initial layout of the buttons
updateScroll()
frame.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(frame)
end
end)
dropDownMenu.MouseButton1Click:connect(toggleVisibility)
areaSoak.MouseButton1Click:connect(toggleVisibility)
return frame, updateSelection
end
t.CreatePropertyDropDownMenu = function(instance, property, enum)
local items = enum:GetEnumItems()
local names = {}
local nameToItem = {}
for i,obj in ipairs(items) do
names[i] = obj.Name
nameToItem[obj.Name] = obj
end
local frame
local updateSelection
frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
ScopedConnect(frame, instance, "Changed",
function(prop)
if prop == property then
updateSelection(instance[property].Name)
end
end,
function()
updateSelection(instance[property].Name)
end)
return frame
end
t.GetFontHeight = function(font, fontSize)
if font == nil or fontSize == nil then
error("Font and FontSize must be non-nil")
end
if font == Enum.Font.Legacy then
if fontSize == Enum.FontSize.Size8 then
return 12
elseif fontSize == Enum.FontSize.Size9 then
return 14
elseif fontSize == Enum.FontSize.Size10 then
return 15
elseif fontSize == Enum.FontSize.Size11 then
return 17
elseif fontSize == Enum.FontSize.Size12 then
return 18
elseif fontSize == Enum.FontSize.Size14 then
return 21
elseif fontSize == Enum.FontSize.Size18 then
return 27
elseif fontSize == Enum.FontSize.Size24 then
return 36
elseif fontSize == Enum.FontSize.Size36 then
return 54
elseif fontSize == Enum.FontSize.Size48 then
return 72
else
error("Unknown FontSize")
end
elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
if fontSize == Enum.FontSize.Size8 then
return 8
elseif fontSize == Enum.FontSize.Size9 then
return 9
elseif fontSize == Enum.FontSize.Size10 then
return 10
elseif fontSize == Enum.FontSize.Size11 then
return 11
elseif fontSize == Enum.FontSize.Size12 then
return 12
elseif fontSize == Enum.FontSize.Size14 then
return 14
elseif fontSize == Enum.FontSize.Size18 then
return 18
elseif fontSize == Enum.FontSize.Size24 then
return 24
elseif fontSize == Enum.FontSize.Size36 then
return 36
elseif fontSize == Enum.FontSize.Size48 then
return 48
else
error("Unknown FontSize")
end
else
error("Unknown Font " .. font)
end
end
local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
for i, child in ipairs(guiObjects) do
if child:IsA("TextLabel") or child:IsA("TextButton") then
local isLabel = child:IsA("TextLabel")
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
if child.TextFits and child.TextBounds.Y < pixelsRemaining then
child.Visible = true
if isLabel then
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
else
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
end
while not child.TextFits do
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
end
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
else
child.Visible = false
pixelsRemaining = -1
end
else
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
child.Visible = (pixelsRemaining >= 0)
end
end
end
t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
if not frame:IsA("GuiObject") then
error("Frame must be a GuiObject")
end
for i, child in ipairs(guiObjects) do
if not child:IsA("GuiObject") then
error("All elements that are layed out must be of type GuiObject")
end
end
if not settingsTable then
settingsTable = {}
end
if not settingsTable["TextLabelSizePadY"] then
settingsTable["TextLabelSizePadY"] = 0
end
if not settingsTable["TextLabelPositionPadY"] then
settingsTable["TextLabelPositionPadY"] = 0
end
if not settingsTable["TextButtonSizePadY"] then
settingsTable["TextButtonSizePadY"] = 12
end
if not settingsTable["TextButtonPositionPadY"] then
settingsTable["TextButtonPositionPadY"] = 2
end
--Wrapper frame takes care of styled objects
local wrapperFrame = Instance.new("Frame")
wrapperFrame.Name = "WrapperFrame"
wrapperFrame.BackgroundTransparency = 1
wrapperFrame.Size = UDim2.new(1,0,1,0)
wrapperFrame.Parent = frame
for i, child in ipairs(guiObjects) do
child.Parent = wrapperFrame
end
local recalculate = function()
wait()
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(recalculate)
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
t.CreateSlider = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 4
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local bar = Instance.new("TextButton")
bar.Text = ""
bar.AutoButtonColor = false
bar.Name = "Bar"
bar.BackgroundColor3 = Color3.new(0,0,0)
if type(width) == "number" then
bar.Size = UDim2.new(0,width,0,5)
else
bar.Size = UDim2.new(0,200,0,5)
end
bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
bar.ZIndex = 2
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/Slider.png"
slider.Position = UDim2.new(0,0,0.5,-10)
slider.Size = UDim2.new(0,20,0,20)
slider.ZIndex = 3
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,10)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(10, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (10 - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateSliderNew = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 6
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local sliderBarImgHeight = 7
local sliderBarCapImgWidth = 4
local bar = Instance.new("ImageButton")
bar.BackgroundTransparency = 1
bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png"
bar.Name = "Bar"
local displayWidth = 200
if type(width) == "number" then
bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight)
displayWidth = width - (sliderBarCapImgWidth * 2)
else
bar.Size = UDim2.new(0,200,0,sliderBarImgHeight)
end
bar.ZIndex = 3
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local barLeft = bar:clone()
barLeft.Name = "BarLeft"
barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png"
barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight)
barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset)
barLeft.Parent = sliderGui
barLeft.ZIndex = 3
local barRight = barLeft:clone()
barRight.Name = "BarRight"
barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png"
barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset)
barRight.Parent = sliderGui
local fillLeft = barLeft:clone()
fillLeft.Name = "FillLeft"
fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png"
fillLeft.Parent = sliderGui
fillLeft.ZIndex = 4
local fill = fillLeft:clone()
fill.Name = "Fill"
fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png"
fill.Parent = bar
fill.ZIndex = 4
fill.Position = UDim2.new(0, 0, 0, 0)
fill.Size = UDim2.new(0.5, 0, 1, 0)
-- bar.Visible = false
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/slider_new_tab.png"
slider.Position = UDim2.new(0,0,0.5,-14)
slider.Size = UDim2.new(0,28,0,28)
slider.ZIndex = 5
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
fill.Size = UDim2.new(relativePosX, 0, 1, 0)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateTrueScrollingFrame = function()
local lowY = nil
local highY = nil
local dragCon = nil
local upCon = nil
local internalChange = false
local descendantsChangeConMap = {}
local scrollingFrame = Instance.new("Frame")
scrollingFrame.Name = "ScrollingFrame"
scrollingFrame.Active = true
scrollingFrame.Size = UDim2.new(1,0,1,0)
scrollingFrame.ClipsDescendants = true
local controlFrame = Instance.new("Frame")
controlFrame.Name = "ControlFrame"
controlFrame.BackgroundTransparency = 1
controlFrame.Size = UDim2.new(0,18,1,0)
controlFrame.Position = UDim2.new(1,-20,0,0)
controlFrame.Parent = scrollingFrame
local scrollBottom = Instance.new("BoolValue")
scrollBottom.Value = false
scrollBottom.Name = "ScrollBottom"
scrollBottom.Parent = controlFrame
local scrollUp = Instance.new("BoolValue")
scrollUp.Value = false
scrollUp.Name = "scrollUp"
scrollUp.Parent = controlFrame
local scrollUpButton = Instance.new("TextButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.Text = ""
scrollUpButton.AutoButtonColor = false
scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
scrollUpButton.BorderColor3 = Color3.new(1,1,1)
scrollUpButton.BackgroundTransparency = 0.5
scrollUpButton.Size = UDim2.new(0,18,0,18)
scrollUpButton.ZIndex = 2
scrollUpButton.Parent = controlFrame
for i = 1, 6 do
local triFrame = Instance.new("Frame")
triFrame.BorderColor3 = Color3.new(1,1,1)
triFrame.Name = "tri" .. tostring(i)
triFrame.ZIndex = 3
triFrame.BackgroundTransparency = 0.5
triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
triFrame.Parent = scrollUpButton
end
scrollUpButton.MouseEnter:connect(function()
scrollUpButton.BackgroundTransparency = 0.1
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.1
end
end)
scrollUpButton.MouseLeave:connect(function()
scrollUpButton.BackgroundTransparency = 0.5
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.5
end
end)
local scrollDownButton = scrollUpButton:clone()
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.Position = UDim2.new(0,0,1,-18)
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
end
scrollDownButton.MouseEnter:connect(function()
scrollDownButton.BackgroundTransparency = 0.1
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.1
end
end)
scrollDownButton.MouseLeave:connect(function()
scrollDownButton.BackgroundTransparency = 0.5
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.5
end
end)
scrollDownButton.Parent = controlFrame
local scrollTrack = Instance.new("Frame")
scrollTrack.Name = "ScrollTrack"
scrollTrack.BackgroundTransparency = 1
scrollTrack.Size = UDim2.new(0,18,1,-38)
scrollTrack.Position = UDim2.new(0,0,0,19)
scrollTrack.Parent = controlFrame
local scrollbar = Instance.new("TextButton")
scrollbar.BackgroundColor3 = Color3.new(0,0,0)
scrollbar.BorderColor3 = Color3.new(1,1,1)
scrollbar.BackgroundTransparency = 0.5
scrollbar.AutoButtonColor = false
scrollbar.Text = ""
scrollbar.Active = true
scrollbar.Name = "ScrollBar"
scrollbar.ZIndex = 2
scrollbar.BackgroundTransparency = 0.5
scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
scrollbar.Position = UDim2.new(0,0,0,0)
scrollbar.Parent = scrollTrack
local scrollNub = Instance.new("Frame")
scrollNub.Name = "ScrollNub"
scrollNub.BorderColor3 = Color3.new(1,1,1)
scrollNub.Size = UDim2.new(0,10,0,0)
scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
scrollNub.ZIndex = 2
scrollNub.BackgroundTransparency = 0.5
scrollNub.Parent = scrollbar
local newNub = scrollNub:clone()
newNub.Position = UDim2.new(0.5,-5,0.5,-2)
newNub.Parent = scrollbar
local lastNub = scrollNub:clone()
lastNub.Position = UDim2.new(0.5,-5,0.5,2)
lastNub.Parent = scrollbar
scrollbar.MouseEnter:connect(function()
scrollbar.BackgroundTransparency = 0.1
scrollNub.BackgroundTransparency = 0.1
newNub.BackgroundTransparency = 0.1
lastNub.BackgroundTransparency = 0.1
end)
scrollbar.MouseLeave:connect(function()
scrollbar.BackgroundTransparency = 0.5
scrollNub.BackgroundTransparency = 0.5
newNub.BackgroundTransparency = 0.5
lastNub.BackgroundTransparency = 0.5
end)
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local function positionScrollBar(x,y,offset)
local oldPos = scrollbar.Position
if y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
return (oldPos ~= scrollbar.Position)
end
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
return (oldPos ~= scrollbar.Position)
end
local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
if newScaleYPos + relativeSize > 1 then
newScaleYPos = 1 - relativeSize
scrollBottom.Value = true
scrollUp.Value = false
elseif newScaleYPos <= 0 then
newScaleYPos = 0
scrollUp.Value = true
scrollBottom.Value = false
else
scrollUp.Value = false
scrollBottom.Value = false
end
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
return (oldPos ~= scrollbar.Position)
end
local function drillDownSetHighLow(instance)
if not instance or not instance:IsA("GuiObject") then return end
if instance == controlFrame then return end
if instance:IsDescendantOf(controlFrame) then return end
if not instance.Visible then return end
if lowY and lowY > instance.AbsolutePosition.Y then
lowY = instance.AbsolutePosition.Y
elseif not lowY then
lowY = instance.AbsolutePosition.Y
end
if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
local children = instance:GetChildren()
for i = 1, #children do
drillDownSetHighLow(children[i])
end
end
local function resetHighLow()
local firstChildren = scrollingFrame:GetChildren()
for i = 1, #firstChildren do
drillDownSetHighLow(firstChildren[i])
end
end
local function recalculate()
internalChange = true
local percentFrame = 0
if scrollbar.Position.Y.Scale > 0 then
if scrollbar.Visible then
percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
else
percentFrame = 0
end
end
if percentFrame > 0.99 then percentFrame = 1 end
local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
local guiChildren = scrollingFrame:GetChildren()
for i = 1, #guiChildren do
if guiChildren[i] ~= controlFrame then
guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
end
end
lowY = nil
highY = nil
resetHighLow()
internalChange = false
end
local function setSliderSizeAndPosition()
if not highY or not lowY then return end
local totalYSpan = math.abs(highY - lowY)
if totalYSpan == 0 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
return
end
local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
if percentShown >= 1 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
recalculate()
else
scrollbar.Visible = true
scrollDownButton.Visible = true
scrollUpButton.Visible = true
scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
end
local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
end
if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
end
end
local buttonScrollAmountPixels = 7
local reentrancyGuardScrollUp = false
local function doScrollUp()
if reentrancyGuardScrollUp then return end
reentrancyGuardScrollUp = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollUp = false
end
local reentrancyGuardScrollDown = false
local function doScrollDown()
if reentrancyGuardScrollDown then return end
reentrancyGuardScrollDown = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollDown = false
end
local function scrollUp(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local function scrollDown(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
scrollbar.MouseButton1Down:connect(function(x,y)
if scrollbar.Active then
scrollStamp = tick()
local mouseOffset = y - scrollbar.AbsolutePosition.y
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
local prevY = y
local reentrancyGuardMouseScroll = false
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
if reentrancyGuardMouseScroll then return end
reentrancyGuardMouseScroll = true
if positionScrollBar(x,y,mouseOffset) then
recalculate()
end
reentrancyGuardMouseScroll = false
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
local function heightCheck(instance)
if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
setSliderSizeAndPosition()
end
local function highLowRecheck()
local oldLowY = lowY
local oldHighY = highY
lowY = nil
highY = nil
resetHighLow()
if (lowY ~= oldLowY) or (highY ~= oldHighY) then
setSliderSizeAndPosition()
end
end
local function descendantChanged(this, prop)
if internalChange then return end
if not this.Visible then return end
if prop == "Size" or prop == "Position" then
wait()
highLowRecheck()
end
end
scrollingFrame.DescendantAdded:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if instance.Visible then
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end
descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
end)
scrollingFrame.DescendantRemoving:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if descendantsChangeConMap[instance] then
descendantsChangeConMap[instance]:disconnect()
descendantsChangeConMap[instance] = nil
end
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end)
scrollingFrame.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if not highY or not lowY then return end
highLowRecheck()
setSliderSizeAndPosition()
end
end)
return scrollingFrame, controlFrame
end
t.CreateScrollingFrame = function(orderList,scrollStyle)
local frame = Instance.new("Frame")
frame.Name = "ScrollingFrame"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1,0,1,0)
local scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
local scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
local scrollbar = Instance.new("ImageButton")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, 0, 150)
local scrollStamp = 0
local scrollDrag = Instance.new("ImageButton")
scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186"
scrollDrag.Size = UDim2.new(1, 0, 0, 16)
scrollDrag.BackgroundTransparency = 1
scrollDrag.Name = "ScrollDrag"
scrollDrag.Active = true
scrollDrag.Parent = scrollbar
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local style = "simple"
if scrollStyle and tostring(scrollStyle) then
style = scrollStyle
end
local scrollPosition = 1
local rowSize = 0
local howManyDisplayed = 0
local layoutGridScrollBar = function()
howManyDisplayed = 0
local guiObjects = {}
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
if scrollPosition < 1 then scrollPosition = 1 end
local totalPixelsY = frame.AbsoluteSize.Y
local pixelsRemainingY = frame.AbsoluteSize.Y
local totalPixelsX = frame.AbsoluteSize.X
local xCounter = 0
local rowSizeCounter = 0
local setRowSize = true
local pixelsBelowScrollbar = 0
local pos = #guiObjects
local currentRowY = 0
pos = scrollPosition
--count up from current scroll position to fill out grid
while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
--previous pos was the end of a row
if xCounter >= totalPixelsX then
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
xCounter = guiObjects[pos].AbsoluteSize.X
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos + 1
end
--Count wherever current row left off
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
pos = scrollPosition - 1
xCounter = 0
--objects with varying X,Y dimensions can rarely cause minor errors
--rechecking every new scrollPosition is necessary to avoid 100% of errors
--count backwards from current scrollPosition to see if we can add more rows
while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
rowSizeCounter = rowSizeCounter + 1
if xCounter >= totalPixelsX then
rowSize = rowSizeCounter - 1
rowSizeCounter = 0
xCounter = guiObjects[pos].AbsoluteSize.X
if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
if scrollPosition <= rowSize then
scrollPosition = 1
break
else
scrollPosition = scrollPosition - rowSize
end
currentRowY = 0
else
break
end
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos - 1
end
--Do check last time if pos = 0
if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
scrollPosition = 1
end
xCounter = 0
--pos = scrollPosition
rowSizeCounter = 0
setRowSize = true
local lastChildSize = 0
local xOffset,yOffset = 0
if guiObjects[1] then
yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
end
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemainingY < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
if xCounter + child.AbsoluteSize.X >= totalPixelsX then
if setRowSize then
rowSize = rowSizeCounter - 1
setRowSize = false
end
xCounter = 0
pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
end
child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
xCounter = xCounter + child.AbsoluteSize.X
child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
if child.Visible then
howManyDisplayed = howManyDisplayed + 1
end
lastChildSize = child.AbsoluteSize
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
if lastChildSize == 0 then
scrollDownButton.Active = false
else
scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
end
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local layoutSimpleScrollBar = function()
local guiObjects = {}
howManyDisplayed = 0
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
local pixelsBelowScrollbar = 0
local pos = #guiObjects
while pixelsBelowScrollbar < totalPixels and pos >= 1 do
if pos >= scrollPosition then
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
else
if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
if scrollPosition <= 1 then
scrollPosition = 1
break
else
--local ("Backing up ScrollPosition from -- " ..scrollPosition)
scrollPosition = scrollPosition - 1
end
else
break
end
end
pos = pos - 1
end
pos = scrollPosition
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemaining < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if (pixelsRemaining >= 0) then
child.Visible = true
howManyDisplayed = howManyDisplayed + 1
else
child.Visible = false
end
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
scrollDownButton.Active = (pixelsRemaining < 0)
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local moveDragger = function()
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
if not scrollDrag.Parent then return end
local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
if dragSizeY < 16 then dragSizeY = 16 end
scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
if relativeYPos > 1 then relativeYPos = 1
elseif relativeYPos < 0 then relativeYPos = 0 end
local absYPos = 0
if relativeYPos ~= 0 then
absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
end
scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
end
local reentrancyGuard = false
local recalculate = function()
if reentrancyGuard then
return
end
reentrancyGuard = true
wait()
local success, err = nil
if style == "grid" then
success, err = pcall(function() layoutGridScrollBar() end)
elseif style == "simple" then
success, err = pcall(function() layoutSimpleScrollBar() end)
end
if not success then print(err) end
moveDragger()
reentrancyGuard = false
end
local doScrollUp = function()
scrollPosition = (scrollPosition) - rowSize
if scrollPosition < 1 then scrollPosition = 1 end
recalculate(nil)
end
local doScrollDown = function()
scrollPosition = (scrollPosition) + rowSize
recalculate(nil)
end
local scrollUp = function(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local scrollDown = function(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local y = 0
scrollDrag.MouseButton1Down:connect(function(x,y)
if scrollDrag.Active then
scrollStamp = tick()
local mouseOffset = y - scrollDrag.AbsolutePosition.y
local dragCon
local upCon
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
local barAbsPos = scrollbar.AbsolutePosition.y
local barAbsSize = scrollbar.AbsoluteSize.y
local dragAbsSize = scrollDrag.AbsoluteSize.y
local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
y = y - mouseOffset
y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
y = y - barAbsPos
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
local doublePercent = y/(barAbsSize-dragAbsSize)
local rowDiff = rowSize
local totalScrollCount = guiObjects - (howManyDisplayed - 1)
local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
if newScrollPosition < scrollPosition then
rowDiff = -rowDiff
end
if newScrollPosition < 1 then
newScrollPosition = 1
end
scrollPosition = newScrollPosition
recalculate(nil)
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(
function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollbar.MouseButton1Down:connect(
function(x,y)
if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
scrollDown(y)
elseif y < (scrollDrag.AbsolutePosition.y) then
scrollUp(y)
end
end)
frame.ChildAdded:connect(function()
recalculate(nil)
end)
frame.ChildRemoved:connect(function()
recalculate(nil)
end)
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(function() recalculate(nil) end)
return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
end
local function binaryGrow(min, max, fits)
if min > max then
return min
end
local biggestLegal = min
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
biggestLegal = mid
--Try growing
min = mid + 1
else
--Doesn't fit, shrink
max = mid - 1
end
end
return biggestLegal
end
local function binaryShrink(min, max, fits)
if min > max then
return min
end
local smallestLegal = max
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
smallestLegal = mid
--It fits, shrink
max = mid - 1
else
--Doesn't fit, grow
min = mid + 1
end
end
return smallestLegal
end
local function getGuiOwner(instance)
while instance ~= nil do
if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
return instance
end
instance = instance.Parent
end
return nil
end
t.AutoTruncateTextObject = function(textLabel)
local text = textLabel.Text
local fullLabel = textLabel:Clone()
fullLabel.Name = "Full" .. textLabel.Name
fullLabel.BorderSizePixel = 0
fullLabel.BackgroundTransparency = 0
fullLabel.Text = text
fullLabel.TextXAlignment = Enum.TextXAlignment.Center
fullLabel.Position = UDim2.new(0,-3,0,0)
fullLabel.Size = UDim2.new(0,100,1,0)
fullLabel.Visible = false
fullLabel.Parent = textLabel
local shortText = nil
local mouseEnterConnection = nil
local mouseLeaveConnection= nil
local checkForResize = function()
if getGuiOwner(textLabel) == nil then
return
end
textLabel.Text = text
if textLabel.TextFits then
--Tear down the rollover if it is active
if mouseEnterConnection then
mouseEnterConnection:disconnect()
mouseEnterConnection = nil
end
if mouseLeaveConnection then
mouseLeaveConnection:disconnect()
mouseLeaveConnection = nil
end
else
local len = string.len(text)
textLabel.Text = text .. "~"
--Shrink the text
local textSize = binaryGrow(0, len,
function(pos)
if pos == 0 then
textLabel.Text = "~"
else
textLabel.Text = string.sub(text, 1, pos) .. "~"
end
return textLabel.TextFits
end)
shortText = string.sub(text, 1, textSize) .. "~"
textLabel.Text = shortText
--Make sure the fullLabel fits
if not fullLabel.TextFits then
--Already too small, grow it really bit to start
fullLabel.Size = UDim2.new(0, 10000, 1, 0)
end
--Okay, now try to binary shrink it back down
local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
function(size)
fullLabel.Size = UDim2.new(0, size, 1, 0)
return fullLabel.TextFits
end)
fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
--Now setup the rollover effects, if they are currently off
if mouseEnterConnection == nil then
mouseEnterConnection = textLabel.MouseEnter:connect(
function()
fullLabel.ZIndex = textLabel.ZIndex + 1
fullLabel.Visible = true
--textLabel.Text = ""
end)
end
if mouseLeaveConnection == nil then
mouseLeaveConnection = textLabel.MouseLeave:connect(
function()
fullLabel.Visible = false
--textLabel.Text = shortText
end)
end
end
end
textLabel.AncestryChanged:connect(checkForResize)
textLabel.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
checkForResize()
end
end)
checkForResize()
local function changeText(newText)
text = newText
fullLabel.Text = text
checkForResize()
end
return textLabel, changeText
end
local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
if fromPage then
fromPage.Visible = false
if transitionFrame.Visible == false then
transitionFrame.Size = fromPage.Size
transitionFrame.Position = fromPage.Position
end
else
if transitionFrame.Visible == false then
transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
end
end
transitionFrame.Visible = true
currentPageValue.Value = nil
local newsize, newPosition
if toPage then
--Make it visible so it resizes
toPage.Visible = true
newSize = toPage.Size
newPosition = toPage.Position
toPage.Visible = false
else
newSize = UDim2.new(0.0,50,0.0,50)
newPosition = UDim2.new(0.5,-25,0.5,-25)
end
transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
function(state)
if state == Enum.TweenStatus.Completed then
transitionFrame.Visible = false
if toPage then
toPage.Visible = true
currentPageValue.Value = toPage
end
end
end)
end
t.CreateTutorial = function(name, tutorialKey, createButtons)
local frame = Instance.new("Frame")
frame.Name = "Tutorial-" .. name
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
local transitionFrame = Instance.new("Frame")
transitionFrame.Name = "TransitionFrame"
transitionFrame.Style = Enum.FrameStyle.RobloxRound
transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
transitionFrame.Visible = false
transitionFrame.Parent = frame
local currentPageValue = Instance.new("ObjectValue")
currentPageValue.Name = "CurrentTutorialPage"
currentPageValue.Value = nil
currentPageValue.Parent = frame
local boolValue = Instance.new("BoolValue")
boolValue.Name = "Buttons"
boolValue.Value = createButtons
boolValue.Parent = frame
local pages = Instance.new("Frame")
pages.Name = "Pages"
pages.BackgroundTransparency = 1
pages.Size = UDim2.new(1,0,1,0)
pages.Parent = frame
local function getVisiblePageAndHideOthers()
local visiblePage = nil
local children = pages:GetChildren()
if children then
for i,child in ipairs(children) do
if child.Visible then
if visiblePage then
child.Visible = false
else
visiblePage = child
end
end
end
end
return visiblePage
end
local showTutorial = function(alwaysShow)
if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
print("Showing tutorial-",tutorialKey)
local currentTutorialPage = getVisiblePageAndHideOthers()
local firstPage = pages:FindFirstChild("TutorialPage1")
if firstPage then
TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
else
error("Could not find TutorialPage1")
end
end
end
local dismissTutorial = function()
local currentTutorialPage = getVisiblePageAndHideOthers()
if currentTutorialPage then
TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
end
UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
end
local gotoPage = function(pageNum)
local page = pages:FindFirstChild("TutorialPage" .. pageNum)
local currentTutorialPage = getVisiblePageAndHideOthers()
TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
end
return frame, showTutorial, dismissTutorial, gotoPage
end
local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
local frame = Instance.new("Frame")
frame.Name = "TutorialPage"
frame.Style = Enum.FrameStyle.RobloxRound
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
frame.Visible = false
local frameHeader = Instance.new("TextLabel")
frameHeader.Name = "Header"
frameHeader.Text = name
frameHeader.BackgroundTransparency = 1
frameHeader.FontSize = Enum.FontSize.Size24
frameHeader.Font = Enum.Font.ArialBold
frameHeader.TextColor3 = Color3.new(1,1,1)
frameHeader.TextXAlignment = Enum.TextXAlignment.Center
frameHeader.TextWrap = true
frameHeader.Size = UDim2.new(1,-55, 0, 22)
frameHeader.Position = UDim2.new(0,0,0,0)
frameHeader.Parent = frame
local skipButton = Instance.new("ImageButton")
skipButton.Name = "SkipButton"
skipButton.AutoButtonColor = false
skipButton.BackgroundTransparency = 1
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
skipButton.MouseButton1Click:connect(function()
skipTutorial()
end)
skipButton.MouseEnter:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
end)
skipButton.MouseLeave:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
end)
skipButton.Size = UDim2.new(0, 25, 0, 25)
skipButton.Position = UDim2.new(1, -25, 0, 0)
skipButton.Parent = frame
if giveDoneButton then
local doneButton = Instance.new("TextButton")
doneButton.Name = "DoneButton"
doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
doneButton.Text = "Done"
doneButton.TextColor3 = Color3.new(1,1,1)
doneButton.Font = Enum.Font.ArialBold
doneButton.FontSize = Enum.FontSize.Size18
doneButton.Size = UDim2.new(0,100,0,50)
doneButton.Position = UDim2.new(0.5,-50,1,-50)
if skipTutorial then
doneButton.MouseButton1Click:connect(function() skipTutorial() end)
end
doneButton.Parent = frame
end
local innerFrame = Instance.new("Frame")
innerFrame.Name = "ContentFrame"
innerFrame.BackgroundTransparency = 1
innerFrame.Position = UDim2.new(0,0,0,25)
innerFrame.Parent = frame
local nextButton = Instance.new("TextButton")
nextButton.Name = "NextButton"
nextButton.Text = "Next"
nextButton.TextColor3 = Color3.new(1,1,1)
nextButton.Font = Enum.Font.Arial
nextButton.FontSize = Enum.FontSize.Size18
nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
nextButton.Size = UDim2.new(0,80, 0, 32)
nextButton.Position = UDim2.new(0.5, 5, 1, -32)
nextButton.Active = false
nextButton.Visible = false
nextButton.Parent = frame
local prevButton = Instance.new("TextButton")
prevButton.Name = "PrevButton"
prevButton.Text = "Previous"
prevButton.TextColor3 = Color3.new(1,1,1)
prevButton.Font = Enum.Font.Arial
prevButton.FontSize = Enum.FontSize.Size18
prevButton.Style = Enum.ButtonStyle.RobloxButton
prevButton.Size = UDim2.new(0,80, 0, 32)
prevButton.Position = UDim2.new(0.5, -85, 1, -32)
prevButton.Active = false
prevButton.Visible = false
prevButton.Parent = frame
if giveDoneButton then
innerFrame.Size = UDim2.new(1,0,1,-75)
else
innerFrame.Size = UDim2.new(1,0,1,-22)
end
local parentConnection = nil
local function basicHandleResize()
if frame.Visible and frame.Parent then
local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
handleResize(200,maxSize)
end
end
frame.Changed:connect(
function(prop)
if prop == "Parent" then
if parentConnection ~= nil then
parentConnection:disconnect()
parentConnection = nil
end
if frame.Parent and frame.Parent:IsA("GuiObject") then
parentConnection = frame.Parent.Changed:connect(
function(parentProp)
if parentProp == "AbsoluteSize" then
wait()
basicHandleResize()
end
end)
basicHandleResize()
end
end
if prop == "Visible" then
basicHandleResize()
end
end)
return frame, innerFrame
end
t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
local frame = nil
local contentFrame = nil
local textLabel = Instance.new("TextLabel")
textLabel.BackgroundTransparency = 1
textLabel.TextColor3 = Color3.new(1,1,1)
textLabel.Text = text
textLabel.TextWrap = true
textLabel.TextXAlignment = Enum.TextXAlignment.Left
textLabel.TextYAlignment = Enum.TextYAlignment.Center
textLabel.Font = Enum.Font.Arial
textLabel.FontSize = Enum.FontSize.Size14
textLabel.Size = UDim2.new(1,0,1,0)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
frame.Size = UDim2.new(0, size, 0, size)
return textLabel.TextFits
end)
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
textLabel.Parent = contentFrame
return frame
end
t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
local frame = nil
local contentFrame = nil
local imageLabel = Instance.new("ImageLabel")
imageLabel.BackgroundTransparency = 1
imageLabel.Image = imageAsset
imageLabel.Size = UDim2.new(0,x,0,y)
imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
return size >= x and size >= y
end)
if size >= x and size >= y then
imageLabel.Size = UDim2.new(0,x, 0,y)
imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
else
if x > y then
--X is limiter, so
imageLabel.Size = UDim2.new(1,0,y/x,0)
imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
else
--Y is limiter
imageLabel.Size = UDim2.new(x/y,0,1, 0)
imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
end
end
size = size + 50
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
imageLabel.Parent = contentFrame
return frame
end
t.AddTutorialPage = function(tutorial, tutorialPage)
local transitionFrame = tutorial.TransitionFrame
local currentPageValue = tutorial.CurrentTutorialPage
if not tutorial.Buttons.Value then
tutorialPage.NextButton.Parent = nil
tutorialPage.PrevButton.Parent = nil
end
local children = tutorial.Pages:GetChildren()
if children and #children > 0 then
tutorialPage.Name = "TutorialPage" .. (#children+1)
local previousPage = children[#children]
if not previousPage:IsA("GuiObject") then
error("All elements under Pages must be GuiObjects")
end
if tutorial.Buttons.Value then
if previousPage.NextButton.Active then
error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
end
previousPage.NextButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
end)
previousPage.NextButton.Active = true
previousPage.NextButton.Visible = true
if tutorialPage.PrevButton.Active then
error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
end
tutorialPage.PrevButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
end)
tutorialPage.PrevButton.Active = true
tutorialPage.PrevButton.Visible = true
end
tutorialPage.Parent = tutorial.Pages
else
--First child
tutorialPage.Name = "TutorialPage1"
tutorialPage.Parent = tutorial.Pages
end
end
t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
if not userIdsForSets then
error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
end
if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
end
if not objectSelected then
error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
end
if type(objectSelected) ~= "function" then
error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
end
if dialogClosed and type(dialogClosed) ~= "function" then
error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
end
if showAdminCategories == nil then -- by default, don't show beta sets
showAdminCategories = false
end
local arrayPosition = 1
local insertButtons = {}
local insertButtonCons = {}
local contents = nil
local setGui = nil
-- used for water selections
local waterForceDirection = "NegX"
local waterForce = "None"
local waterGui, waterTypeChangedEvent = nil
local Data = {}
Data.CurrentCategory = nil
Data.Category = {}
local SetCache = {}
local userCategoryButtons = nil
local buttonWidth = 64
local buttonHeight = buttonWidth
local SmallThumbnailUrl = nil
local LargeThumbnailUrl = nil
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if useAssetVersionId then
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
else
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
end
local function drillDownSetZIndex(parent, index)
local children = parent:GetChildren()
for i = 1, #children do
if children[i]:IsA("GuiObject") then
children[i].ZIndex = index
end
drillDownSetZIndex(children[i], index)
end
end
-- for terrain stamping
local currTerrainDropDownFrame = nil
local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
local terrainShapeMap = {}
for i = 1, #terrainShapes do
terrainShapeMap[terrainShapes[i]] = i - 1
end
terrainShapeMap[terrainShapes[#terrainShapes]] = 6
local function createWaterGui()
local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
local waterFrame = Instance.new("Frame")
waterFrame.Name = "WaterFrame"
waterFrame.Style = Enum.FrameStyle.RobloxSquare
waterFrame.Size = UDim2.new(0,150,0,110)
waterFrame.Visible = false
local waterForceLabel = Instance.new("TextLabel")
waterForceLabel.Name = "WaterForceLabel"
waterForceLabel.BackgroundTransparency = 1
waterForceLabel.Size = UDim2.new(1,0,0,12)
waterForceLabel.Font = Enum.Font.ArialBold
waterForceLabel.FontSize = Enum.FontSize.Size12
waterForceLabel.TextColor3 = Color3.new(1,1,1)
waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
waterForceLabel.Text = "Water Force"
waterForceLabel.Parent = waterFrame
local waterForceDirLabel = waterForceLabel:Clone()
waterForceDirLabel.Name = "WaterForceDirectionLabel"
waterForceDirLabel.Text = "Water Force Direction"
waterForceDirLabel.Position = UDim2.new(0,0,0,50)
waterForceDirLabel.Parent = waterFrame
local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
local waterForceDirectionSelectedFunc = function(newForceDirection)
waterForceDirection = newForceDirection
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceSelectedFunc = function(newForce)
waterForce = newForce
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
forceWaterDirectionSelection("NegX")
waterForceDirectionDropDown.Parent = waterForceDirLabel
local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
forceWaterForceSelection("None")
waterForceDropDown.Size = UDim2.new(1,0,0,25)
waterForceDropDown.Position = UDim2.new(0,0,1,3)
waterForceDropDown.Parent = waterForceLabel
return waterFrame, waterTypeChangedEvent
end
-- Helper Function that contructs gui elements
local function createSetGui()
local setGui = Instance.new("ScreenGui")
setGui.Name = "SetGui"
local setPanel = Instance.new("Frame")
setPanel.Name = "SetPanel"
setPanel.Active = true
setPanel.BackgroundTransparency = 1
if position then
setPanel.Position = position
else
setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
end
if size then
setPanel.Size = size
else
setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
end
setPanel.Style = Enum.FrameStyle.RobloxRound
setPanel.ZIndex = 6
setPanel.Parent = setGui
-- Children of SetPanel
local itemPreview = Instance.new("Frame")
itemPreview.Name = "ItemPreview"
itemPreview.BackgroundTransparency = 1
itemPreview.Position = UDim2.new(0.8,5,0.085,0)
itemPreview.Size = UDim2.new(0.21,0,0.9,0)
itemPreview.ZIndex = 6
itemPreview.Parent = setPanel
-- Children of ItemPreview
local textPanel = Instance.new("Frame")
textPanel.Name = "TextPanel"
textPanel.BackgroundTransparency = 1
textPanel.Position = UDim2.new(0,0,0.45,0)
textPanel.Size = UDim2.new(1,0,0.55,0)
textPanel.ZIndex = 6
textPanel.Parent = itemPreview
-- Children of TextPanel
local rolloverText = Instance.new("TextLabel")
rolloverText.Name = "RolloverText"
rolloverText.BackgroundTransparency = 1
rolloverText.Size = UDim2.new(1,0,0,48)
rolloverText.ZIndex = 6
rolloverText.Font = Enum.Font.ArialBold
rolloverText.FontSize = Enum.FontSize.Size24
rolloverText.Text = ""
rolloverText.TextColor3 = Color3.new(1,1,1)
rolloverText.TextWrap = true
rolloverText.TextXAlignment = Enum.TextXAlignment.Left
rolloverText.TextYAlignment = Enum.TextYAlignment.Top
rolloverText.Parent = textPanel
local largePreview = Instance.new("ImageLabel")
largePreview.Name = "LargePreview"
largePreview.BackgroundTransparency = 1
largePreview.Image = ""
largePreview.Size = UDim2.new(1,0,0,170)
largePreview.ZIndex = 6
largePreview.Parent = itemPreview
local sets = Instance.new("Frame")
sets.Name = "Sets"
sets.BackgroundTransparency = 1
sets.Position = UDim2.new(0,0,0,5)
sets.Size = UDim2.new(0.23,0,1,-5)
sets.ZIndex = 6
sets.Parent = setPanel
-- Children of Sets
local line = Instance.new("Frame")
line.Name = "Line"
line.BackgroundColor3 = Color3.new(1,1,1)
line.BackgroundTransparency = 0.7
line.BorderSizePixel = 0
line.Position = UDim2.new(1,-3,0.06,0)
line.Size = UDim2.new(0,3,0.9,0)
line.ZIndex = 6
line.Parent = sets
local setsLists, controlFrame = t.CreateTrueScrollingFrame()
setsLists.Size = UDim2.new(1,-6,0.94,0)
setsLists.Position = UDim2.new(0,0,0.06,0)
setsLists.BackgroundTransparency = 1
setsLists.Name = "SetsLists"
setsLists.ZIndex = 6
setsLists.Parent = sets
drillDownSetZIndex(controlFrame, 7)
local setsHeader = Instance.new("TextLabel")
setsHeader.Name = "SetsHeader"
setsHeader.BackgroundTransparency = 1
setsHeader.Size = UDim2.new(0,47,0,24)
setsHeader.ZIndex = 6
setsHeader.Font = Enum.Font.ArialBold
setsHeader.FontSize = Enum.FontSize.Size24
setsHeader.Text = "Sets"
setsHeader.TextColor3 = Color3.new(1,1,1)
setsHeader.TextXAlignment = Enum.TextXAlignment.Left
setsHeader.TextYAlignment = Enum.TextYAlignment.Top
setsHeader.Parent = sets
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(1,-32,0,-2)
cancelButton.Size = UDim2.new(0,34,0,34)
cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
cancelButton.ZIndex = 6
cancelButton.Text = ""
cancelButton.Modal = true
cancelButton.Parent = setPanel
-- Children of Cancel Button
local cancelImage = Instance.new("ImageLabel")
cancelImage.Name = "CancelImage"
cancelImage.BackgroundTransparency = 1
cancelImage.Image = "http://www.roblox.com/asset/?id=54135717"
cancelImage.Position = UDim2.new(0,-2,0,-2)
cancelImage.Size = UDim2.new(0,16,0,16)
cancelImage.ZIndex = 6
cancelImage.Parent = cancelButton
return setGui
end
local function createSetButton(text)
local setButton = Instance.new("TextButton")
if text then setButton.Text = text
else setButton.Text = "" end
setButton.AutoButtonColor = false
setButton.BackgroundTransparency = 1
setButton.BackgroundColor3 = Color3.new(1,1,1)
setButton.BorderSizePixel = 0
setButton.Size = UDim2.new(1,-5,0,18)
setButton.ZIndex = 6
setButton.Visible = false
setButton.Font = Enum.Font.Arial
setButton.FontSize = Enum.FontSize.Size18
setButton.TextColor3 = Color3.new(1,1,1)
setButton.TextXAlignment = Enum.TextXAlignment.Left
return setButton
end
local function buildSetButton(name, setId, setImageId, i, count)
local button = createSetButton(name)
button.Text = name
button.Name = "SetButton"
button.Visible = true
local setValue = Instance.new("IntValue")
setValue.Name = "SetId"
setValue.Value = setId
setValue.Parent = button
local setName = Instance.new("StringValue")
setName.Name = "SetName"
setName.Value = name
setName.Parent = button
return button
end
local function processCategory(sets)
local setButtons = {}
local numSkipped = 0
for i = 1, #sets do
if not showAdminCategories and sets[i].Name == "Beta" then
numSkipped = numSkipped + 1
else
setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
end
end
return setButtons
end
local function handleResize()
wait() -- neccessary to insure heartbeat happened
local itemPreview = setGui.SetPanel.ItemPreview
itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
end
local function makeInsertAssetButton()
local insertAssetButtonExample = Instance.new("Frame")
insertAssetButtonExample.Name = "InsertAssetButtonExample"
insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
insertAssetButtonExample.BackgroundTransparency = 1
insertAssetButtonExample.ZIndex = 6
insertAssetButtonExample.Visible = false
local assetId = Instance.new("IntValue")
assetId.Name = "AssetId"
assetId.Value = 0
assetId.Parent = insertAssetButtonExample
local assetName = Instance.new("StringValue")
assetName.Name = "AssetName"
assetName.Value = ""
assetName.Parent = insertAssetButtonExample
local button = Instance.new("TextButton")
button.Name = "Button"
button.Text = ""
button.Style = Enum.ButtonStyle.RobloxButton
button.Position = UDim2.new(0.025,0,0.025,0)
button.Size = UDim2.new(0.95,0,0.95,0)
button.ZIndex = 6
button.Parent = insertAssetButtonExample
local buttonImage = Instance.new("ImageLabel")
buttonImage.Name = "ButtonImage"
buttonImage.Image = ""
buttonImage.Position = UDim2.new(0,-7,0,-7)
buttonImage.Size = UDim2.new(1,14,1,14)
buttonImage.BackgroundTransparency = 1
buttonImage.ZIndex = 7
buttonImage.Parent = button
local configIcon = buttonImage:clone()
configIcon.Name = "ConfigIcon"
configIcon.Visible = false
configIcon.Position = UDim2.new(1,-23,1,-24)
configIcon.Size = UDim2.new(0,16,0,16)
configIcon.Image = ""
configIcon.ZIndex = 6
configIcon.Parent = insertAssetButtonExample
return insertAssetButtonExample
end
local function showLargePreview(insertButton)
if insertButton:FindFirstChild("AssetId") then
delay(0,function()
game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
end)
end
if insertButton:FindFirstChild("AssetName") then
setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
end
end
local function selectTerrainShape(shape)
if currTerrainDropDownFrame then
objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
end
end
local function createTerrainTypeButton(name, parent)
local dropDownTextButton = Instance.new("TextButton")
dropDownTextButton.Name = name .. "Button"
dropDownTextButton.Font = Enum.Font.ArialBold
dropDownTextButton.FontSize = Enum.FontSize.Size14
dropDownTextButton.BorderSizePixel = 0
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
dropDownTextButton.Text = name
dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.ZIndex = parent.ZIndex + 1
dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
dropDownTextButton.Position = UDim2.new(0,1,0,0)
dropDownTextButton.MouseEnter:connect(function()
dropDownTextButton.BackgroundTransparency = 0
dropDownTextButton.TextColor3 = Color3.new(0,0,0)
end)
dropDownTextButton.MouseLeave:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
end)
dropDownTextButton.MouseButton1Click:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
dropDownTextButton.Parent.Visible = false
end
selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
end)
return dropDownTextButton
end
local function createTerrainDropDownMenu(zIndex)
local dropDown = Instance.new("Frame")
dropDown.Name = "TerrainDropDown"
dropDown.BackgroundColor3 = Color3.new(0,0,0)
dropDown.BorderColor3 = Color3.new(1,0,0)
dropDown.Size = UDim2.new(0,200,0,0)
dropDown.Visible = false
dropDown.ZIndex = zIndex
dropDown.Parent = setGui
for i = 1, #terrainShapes do
local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
shapeButton.Parent = dropDown
dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
end
dropDown.MouseLeave:connect(function()
dropDown.Visible = false
end)
end
local function createDropDownMenuButton(parent)
local dropDownButton = Instance.new("ImageButton")
dropDownButton.Name = "DropDownButton"
dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509"
dropDownButton.BackgroundTransparency = 1
dropDownButton.Size = UDim2.new(0,16,0,16)
dropDownButton.Position = UDim2.new(1,-24,0,6)
dropDownButton.ZIndex = parent.ZIndex + 2
dropDownButton.Parent = parent
if not setGui:FindFirstChild("TerrainDropDown") then
createTerrainDropDownMenu(8)
end
dropDownButton.MouseButton1Click:connect(function()
setGui.TerrainDropDown.Visible = true
setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
currTerrainDropDownFrame = parent
end)
end
local function buildInsertButton()
local insertButton = makeInsertAssetButton()
insertButton.Name = "InsertAssetButton"
insertButton.Visible = true
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
createDropDownMenuButton(insertButton)
end
local lastEnter = nil
local mouseEnterCon = insertButton.MouseEnter:connect(function()
lastEnter = insertButton
delay(0.1,function()
if lastEnter == insertButton then
showLargePreview(insertButton)
end
end)
end)
return insertButton, mouseEnterCon
end
local function realignButtonGrid(columns)
local x = 0
local y = 0
for i = 1, #insertButtons do
insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
x = x + 1
if x >= columns then
x = 0
y = y + 1
end
end
end
local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
if visible then
insertFrame.AssetName.Value = name
insertFrame.AssetId.Value = assetId
local newImageUrl = SmallThumbnailUrl .. assetId
if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
delay(0,function()
game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
if insertFrame:findFirstChild("Button") then
insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
end
end)
end
table.insert(insertButtonCons,
insertFrame.Button.MouseButton1Click:connect(function()
-- special case for water, show water selection gui
local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
waterGui.Visible = isWaterSelected
if isWaterSelected then
objectSelected(name, tonumber(assetId), nil)
else
objectSelected(name, tonumber(assetId))
end
end)
)
insertFrame.Visible = true
else
insertFrame.Visible = false
end
end
local function loadSectionOfItems(setGui, rows, columns)
local pageSize = rows * columns
if arrayPosition > #contents then return end
local origArrayPos = arrayPosition
local yCopy = 0
for i = 1, pageSize + 1 do
if arrayPosition >= #contents + 1 then
break
end
local buttonCon
insertButtons[arrayPosition], buttonCon = buildInsertButton()
table.insert(insertButtonCons,buttonCon)
insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
arrayPosition = arrayPosition + 1
end
realignButtonGrid(columns)
local indexCopy = origArrayPos
for index = origArrayPos, arrayPosition do
if insertButtons[index] then
if contents[index] then
-- we don't want water to have a drop down button
if contents[index].Name == "Water" then
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
end
end
local assetId
if useAssetVersionId then
assetId = contents[index].AssetVersionId
else
assetId = contents[index].AssetId
end
setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
else
break
end
else
break
end
indexCopy = index
end
end
local function setSetIndex()
Data.Category[Data.CurrentCategory].Index = 0
rows = 7
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
contents = Data.Category[Data.CurrentCategory].Contents
if contents then
-- remove our buttons and their connections
for i = 1, #insertButtons do
insertButtons[i]:remove()
end
for i = 1, #insertButtonCons do
if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
end
insertButtonCons = {}
insertButtons = {}
arrayPosition = 1
loadSectionOfItems(setGui, rows, columns)
end
end
local function selectSet(button, setName, setId, setIndex)
if button and Data.Category[Data.CurrentCategory] ~= nil then
if button ~= Data.Category[Data.CurrentCategory].Button then
Data.Category[Data.CurrentCategory].Button = button
if SetCache[setId] == nil then
SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
end
Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
Data.Category[Data.CurrentCategory].SetName = setName
Data.Category[Data.CurrentCategory].SetId = setId
end
setSetIndex()
end
end
local function selectCategoryPage(buttons, page)
if buttons ~= Data.CurrentCategory then
if Data.CurrentCategory then
for key, button in pairs(Data.CurrentCategory) do
button.Visible = false
end
end
Data.CurrentCategory = buttons
if Data.Category[Data.CurrentCategory] == nil then
Data.Category[Data.CurrentCategory] = {}
if #buttons > 0 then
selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
end
else
Data.Category[Data.CurrentCategory].Button = nil
selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
end
end
end
local function selectCategory(category)
selectCategoryPage(category, 0)
end
local function resetAllSetButtonSelection()
local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
for i = 1, #setButtons do
if setButtons[i]:IsA("TextButton") then
setButtons[i].Selected = false
setButtons[i].BackgroundTransparency = 1
setButtons[i].TextColor3 = Color3.new(1,1,1)
setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
end
end
end
local function populateSetsFrame()
local currRow = 0
for i = 1, #userCategoryButtons do
local button = userCategoryButtons[i]
button.Visible = true
button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
button.Parent = setGui.SetPanel.Sets.SetsLists
if i == 1 then -- we will have this selected by default, so show it
button.Selected = true
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
end
button.MouseEnter:connect(function()
if not button.Selected then
button.BackgroundTransparency = 0
button.TextColor3 = Color3.new(0,0,0)
end
end)
button.MouseLeave:connect(function()
if not button.Selected then
button.BackgroundTransparency = 1
button.TextColor3 = Color3.new(1,1,1)
end
end)
button.MouseButton1Click:connect(function()
resetAllSetButtonSelection()
button.Selected = not button.Selected
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
end)
currRow = currRow + 1
end
local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
-- set first category as loaded for default
if buttons then
for i = 1, #buttons do
if buttons[i]:IsA("TextButton") then
selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
selectCategory(userCategoryButtons)
break
end
end
end
end
setGui = createSetGui()
waterGui, waterTypeChangedEvent = createWaterGui()
waterGui.Position = UDim2.new(0,55,0,0)
waterGui.Parent = setGui
setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
if prop == "AbsoluteSize" then
handleResize()
setSetIndex()
end
end)
local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
scrollFrame.Name = "ItemsFrame"
scrollFrame.ZIndex = 6
scrollFrame.Parent = setGui.SetPanel
scrollFrame.BackgroundTransparency = 1
drillDownSetZIndex(controlFrame,7)
controlFrame.Parent = setGui.SetPanel
controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
local debounce = false
controlFrame.ScrollBottom.Changed:connect(function(prop)
if controlFrame.ScrollBottom.Value == true then
if debounce then return end
debounce = true
loadSectionOfItems(setGui, rows, columns)
debounce = false
end
end)
local userData = {}
for id = 1, #userIdsForSets do
local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
if newUserData and #newUserData > 2 then
-- start at #3 to skip over My Decals and My Models for each account
for category = 3, #newUserData do
if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
table.insert(userData,1,newUserData[category])
else
table.insert(userData, newUserData[category])
end
end
end
end
if userData then
userCategoryButtons = processCategory(userData)
end
rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
populateSetsFrame()
insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
setGui.SetPanel.Visible = false
if dialogClosed then dialogClosed() end
end)
local setVisibilityFunction = function(visible)
if visible then
setGui.SetPanel.Visible = true
else
setGui.SetPanel.Visible = false
end
end
local getVisibilityFunction = function()
if setGui then
if setGui:FindFirstChild("SetPanel") then
return setGui.SetPanel.Visible
end
end
return false
end
return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
end
t.CreateTerrainMaterialSelector = function(size,position)
local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
local selectedButton = nil
local frame = Instance.new("Frame")
frame.Name = "TerrainMaterialSelector"
if size then
frame.Size = size
else
frame.Size = UDim2.new(0, 245, 0, 230)
end
if position then
frame.Position = position
end
frame.BorderSizePixel = 0
frame.BackgroundColor3 = Color3.new(0,0,0)
frame.Active = true
terrainMaterialSelectionChanged.Parent = frame
local waterEnabled = true -- todo: turn this on when water is ready
local materialToImageMap = {}
local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
if waterEnabled then
table.insert(materialNames,"Water")
end
local currentMaterial = 1
function getEnumFromName(choice)
if choice == "Grass" then return 1 end
if choice == "Sand" then return 2 end
if choice == "Erase" then return 0 end
if choice == "Brick" then return 3 end
if choice == "Granite" then return 4 end
if choice == "Asphalt" then return 5 end
if choice == "Iron" then return 6 end
if choice == "Aluminum" then return 7 end
if choice == "Gold" then return 8 end
if choice == "Plank" then return 9 end
if choice == "Log" then return 10 end
if choice == "Gravel" then return 11 end
if choice == "Cinder Block" then return 12 end
if choice == "Stone Wall" then return 13 end
if choice == "Concrete" then return 14 end
if choice == "Plastic (red)" then return 15 end
if choice == "Plastic (blue)" then return 16 end
if choice == "Water" then return 17 end
end
function getNameFromEnum(choice)
if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
if waterEnabled then
if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
end
end
local function updateMaterialChoice(choice)
currentMaterial = getEnumFromName(choice)
terrainMaterialSelectionChanged:Fire(currentMaterial)
end
-- we so need a better way to do this
for i,v in pairs(materialNames) do
materialToImageMap[v] = {}
if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112"
elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652"
elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537"
elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153"
elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038"
elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093"
elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995"
elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118"
elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848"
elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924"
elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015"
elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051"
elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206"
elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103"
elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804"
elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059"
elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474"
else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!!
end
end
local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
scrollFrame.Size = UDim2.new(0.85,0,1,0)
scrollFrame.Position = UDim2.new(0,0,0,0)
scrollFrame.Parent = frame
scrollUp.Parent = frame
scrollUp.Visible = true
scrollUp.Position = UDim2.new(1,-19,0,0)
scrollDown.Parent = frame
scrollDown.Visible = true
scrollDown.Position = UDim2.new(1,-19,1,-17)
local function goToNewMaterial(buttonWrap, materialName)
updateMaterialChoice(materialName)
buttonWrap.BackgroundTransparency = 0
selectedButton.BackgroundTransparency = 1
selectedButton = buttonWrap
end
local function createMaterialButton(name)
local buttonWrap = Instance.new("TextButton")
buttonWrap.Text = ""
buttonWrap.Size = UDim2.new(0,32,0,32)
buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
buttonWrap.BorderSizePixel = 0
buttonWrap.BackgroundTransparency = 1
buttonWrap.AutoButtonColor = false
buttonWrap.Name = tostring(name)
local imageButton = Instance.new("ImageButton")
imageButton.AutoButtonColor = false
imageButton.BackgroundTransparency = 1
imageButton.Size = UDim2.new(0,30,0,30)
imageButton.Position = UDim2.new(0,1,0,1)
imageButton.Name = tostring(name)
imageButton.Parent = buttonWrap
imageButton.Image = materialToImageMap[name].Regular
local enumType = Instance.new("NumberValue")
enumType.Name = "EnumType"
enumType.Parent = buttonWrap
enumType.Value = 0
imageButton.MouseEnter:connect(function()
buttonWrap.BackgroundTransparency = 0
end)
imageButton.MouseLeave:connect(function()
if selectedButton ~= buttonWrap then
buttonWrap.BackgroundTransparency = 1
end
end)
imageButton.MouseButton1Click:connect(function()
if selectedButton ~= buttonWrap then
goToNewMaterial(buttonWrap, tostring(name))
end
end)
return buttonWrap
end
for i = 1, #materialNames do
local imageButton = createMaterialButton(materialNames[i])
if materialNames[i] == "Grass" then -- always start with grass as the default
selectedButton = imageButton
imageButton.BackgroundTransparency = 0
end
imageButton.Parent = scrollFrame
end
local forceTerrainMaterialSelection = function(newMaterialType)
if not newMaterialType then return end
if currentMaterial == newMaterialType then return end
local matName = getNameFromEnum(newMaterialType)
local buttons = scrollFrame:GetChildren()
for i = 1, #buttons do
if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
if string.find(buttons[i].Name, matName) then
goToNewMaterial(buttons[i],matName)
return
end
end
end
frame.Changed:connect(function ( prop )
if prop == "AbsoluteSize" then
recalculateScroll()
end
end)
recalculateScroll()
return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
end
t.CreateLoadingFrame = function(name,size,position)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053")
local loadingFrame = Instance.new("Frame")
loadingFrame.Name = "LoadingFrame"
loadingFrame.Style = Enum.FrameStyle.RobloxRound
if size then loadingFrame.Size = size
else loadingFrame.Size = UDim2.new(0,300,0,160) end
if position then loadingFrame.Position = position
else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
local loadingBar = Instance.new("Frame")
loadingBar.Name = "LoadingBar"
loadingBar.BackgroundColor3 = Color3.new(0,0,0)
loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
loadingBar.Position = UDim2.new(0,0,0,41)
loadingBar.Size = UDim2.new(1,0,0,30)
loadingBar.Parent = loadingFrame
local loadingGreenBar = Instance.new("ImageLabel")
loadingGreenBar.Name = "LoadingGreenBar"
loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053"
loadingGreenBar.Position = UDim2.new(0,0,0,0)
loadingGreenBar.Size = UDim2.new(0,0,1,0)
loadingGreenBar.Visible = false
loadingGreenBar.Parent = loadingBar
local loadingPercent = Instance.new("TextLabel")
loadingPercent.Name = "LoadingPercent"
loadingPercent.BackgroundTransparency = 1
loadingPercent.Position = UDim2.new(0,0,1,0)
loadingPercent.Size = UDim2.new(1,0,0,14)
loadingPercent.Font = Enum.Font.Arial
loadingPercent.Text = "0%"
loadingPercent.FontSize = Enum.FontSize.Size14
loadingPercent.TextColor3 = Color3.new(1,1,1)
loadingPercent.Parent = loadingBar
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(0.5,-60,1,-40)
cancelButton.Size = UDim2.new(0,120,0,40)
cancelButton.Font = Enum.Font.Arial
cancelButton.FontSize = Enum.FontSize.Size18
cancelButton.TextColor3 = Color3.new(1,1,1)
cancelButton.Text = "Cancel"
cancelButton.Style = Enum.ButtonStyle.RobloxButton
cancelButton.Parent = loadingFrame
local loadingName = Instance.new("TextLabel")
loadingName.Name = "loadingName"
loadingName.BackgroundTransparency = 1
loadingName.Size = UDim2.new(1,0,0,18)
loadingName.Position = UDim2.new(0,0,0,2)
loadingName.Font = Enum.Font.Arial
loadingName.Text = name
loadingName.TextColor3 = Color3.new(1,1,1)
loadingName.TextStrokeTransparency = 1
loadingName.FontSize = Enum.FontSize.Size18
loadingName.Parent = loadingFrame
local cancelButtonClicked = Instance.new("BindableEvent")
cancelButtonClicked.Name = "CancelButtonClicked"
cancelButtonClicked.Parent = cancelButton
cancelButton.MouseButton1Click:connect(function()
cancelButtonClicked:Fire()
end)
local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
if percent and type(percent) ~= "number" then
error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
end
local newSize = nil
if percent < 0 then
newSize = UDim2.new(0,0,1,0)
elseif percent > 1 then
newSize = UDim2.new(1,0,1,0)
else
newSize = UDim2.new(percent,0,1,0)
end
if tweenAction then
if not tweenLength then
error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
end
if (newSize.X.Scale > 0) then
loadingGreenBar.Visible = true
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true)
else
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true,
function()
if (newSize.X.Scale < 0) then
loadingGreenBar.Visible = false
end
end)
end
else
loadingGreenBar.Size = newSize
loadingGreenBar.Visible = (newSize.X.Scale > 0)
end
end
loadingGreenBar.Changed:connect(function(prop)
if prop == "Size" then
loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
end
end)
return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
end
t.CreatePluginFrame = function (name,size,position,scrollable,parent)
function createMenuButton(size,position,text,fontsize,name,parent)
local button = Instance.new("TextButton",parent)
button.AutoButtonColor = false
button.Name = name
button.BackgroundTransparency = 1
button.Position = position
button.Size = size
button.Font = Enum.Font.ArialBold
button.FontSize = fontsize
button.Text = text
button.TextColor3 = Color3.new(1,1,1)
button.BorderSizePixel = 0
button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
button.MouseEnter:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 1
end)
return button
end
local dragBar = Instance.new("Frame",parent)
dragBar.Name = tostring(name) .. "DragBar"
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
dragBar.BorderColor3 = Color3.new(0,0,0)
if size then
dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
else
dragBar.Size = UDim2.new(0,183,0,20)
end
if position then
dragBar.Position = position
end
dragBar.Active = true
dragBar.Draggable = true
--dragBar.Visible = false
dragBar.MouseEnter:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
end)
dragBar.MouseLeave:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end)
-- plugin name label
local pluginNameLabel = Instance.new("TextLabel",dragBar)
pluginNameLabel.Name = "BarNameLabel"
pluginNameLabel.Text = " " .. tostring(name)
pluginNameLabel.TextColor3 = Color3.new(1,1,1)
pluginNameLabel.TextStrokeTransparency = 0
pluginNameLabel.Size = UDim2.new(1,0,1,0)
pluginNameLabel.Font = Enum.Font.ArialBold
pluginNameLabel.FontSize = Enum.FontSize.Size18
pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
pluginNameLabel.BackgroundTransparency = 1
-- close button
local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
local closeEvent = Instance.new("BindableEvent")
closeEvent.Name = "CloseEvent"
closeEvent.Parent = closeButton
closeButton.MouseButton1Click:connect(function ()
closeEvent:Fire()
closeButton.BackgroundTransparency = 1
end)
-- help button
local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
local helpFrame = Instance.new("Frame",dragBar)
helpFrame.Name = "HelpFrame"
helpFrame.BackgroundColor3 = Color3.new(0,0,0)
helpFrame.Size = UDim2.new(0,300,0,552)
helpFrame.Position = UDim2.new(1,5,0,0)
helpFrame.Active = true
helpFrame.BorderSizePixel = 0
helpFrame.Visible = false
helpButton.MouseButton1Click:connect(function( )
helpFrame.Visible = not helpFrame.Visible
if helpFrame.Visible then
helpButton.Selected = true
helpButton.BackgroundTransparency = 0
local screenGui = getScreenGuiAncestor(helpFrame)
if screenGui then
if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
else -- position on right hand side
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpButton.Selected = false
helpButton.BackgroundTransparency = 1
end
end)
local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
local minimizeFrame = Instance.new("Frame",dragBar)
minimizeFrame.Name = "MinimizeFrame"
minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
minimizeFrame.BorderColor3 = Color3.new(0,0,0)
minimizeFrame.Position = UDim2.new(0,0,1,0)
if size then
minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
else
minimizeFrame.Size = UDim2.new(0,183,0,50)
end
minimizeFrame.Visible = false
local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
minimizeBigButton.Name = "MinimizeButton"
minimizeBigButton.Size = UDim2.new(0,100,0,40)
minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
minimizeBigButton.Font = Enum.Font.ArialBold
minimizeBigButton.FontSize = Enum.FontSize.Size18
minimizeBigButton.TextColor3 = Color3.new(1,1,1)
minimizeBigButton.Text = "Show"
local separatingLine = Instance.new("Frame",dragBar)
separatingLine.Name = "SeparatingLine"
separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
separatingLine.BorderSizePixel = 0
separatingLine.Position = UDim2.new(1,-18,0.5,-7)
separatingLine.Size = UDim2.new(0,1,0,14)
local otherSeparatingLine = separatingLine:clone()
otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
otherSeparatingLine.Parent = dragBar
local widgetContainer = Instance.new("Frame",dragBar)
widgetContainer.Name = "WidgetContainer"
widgetContainer.BackgroundTransparency = 1
widgetContainer.Position = UDim2.new(0,0,1,0)
widgetContainer.BorderColor3 = Color3.new(0,0,0)
if not scrollable then
widgetContainer.BackgroundTransparency = 0
widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
end
if size then
if scrollable then
widgetContainer.Size = size
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
end
else
if scrollable then
widgetContainer.Size = UDim2.new(0,163,0,400)
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
end
end
if position then
widgetContainer.Position = position + UDim2.new(0,0,0,20)
end
local frame,control,verticalDragger = nil
if scrollable then
--frame for widgets
frame,control = t.CreateTrueScrollingFrame()
frame.Size = UDim2.new(1, 0, 1, 0)
frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
frame.BorderColor3 = Color3.new(0,0,0)
frame.Active = true
frame.Parent = widgetContainer
control.Parent = dragBar
control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
control.BorderSizePixel = 0
control.BackgroundTransparency = 0
control.Position = UDim2.new(1,-21,1,1)
if size then
control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
else
control.Size = UDim2.new(0,21,0,400)
end
control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
local fakeLine = Instance.new("Frame",control)
fakeLine.Name = "FakeLine"
fakeLine.BorderSizePixel = 0
fakeLine.BackgroundColor3 = Color3.new(0,0,0)
fakeLine.Size = UDim2.new(0,1,1,1)
fakeLine.Position = UDim2.new(1,0,0,0)
verticalDragger = Instance.new("TextButton",widgetContainer)
verticalDragger.ZIndex = 2
verticalDragger.AutoButtonColor = false
verticalDragger.Name = "VerticalDragger"
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
verticalDragger.BorderColor3 = Color3.new(0,0,0)
verticalDragger.Size = UDim2.new(1,20,0,20)
verticalDragger.Position = UDim2.new(0,0,1,0)
verticalDragger.Active = true
verticalDragger.Text = ""
local scrubFrame = Instance.new("Frame",verticalDragger)
scrubFrame.Name = "ScrubFrame"
scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
scrubFrame.BorderSizePixel = 0
scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
scrubFrame.Size = UDim2.new(0,10,0,1)
scrubFrame.ZIndex = 5
local scrubTwo = scrubFrame:clone()
scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
scrubTwo.Parent = verticalDragger
local scrubThree = scrubFrame:clone()
scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
scrubThree.Parent = verticalDragger
local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
areaSoak.Name = "AreaSoak"
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.BackgroundTransparency = 1
areaSoak.BorderSizePixel = 0
areaSoak.Text = ""
areaSoak.ZIndex = 10
areaSoak.Visible = false
areaSoak.Active = true
local draggingVertical = false
local startYPos = nil
verticalDragger.MouseEnter:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
end)
verticalDragger.MouseLeave:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
end)
verticalDragger.MouseButton1Down:connect(function(x,y)
draggingVertical = true
areaSoak.Visible = true
startYPos = y
end)
areaSoak.MouseButton1Up:connect(function ( )
draggingVertical = false
areaSoak.Visible = false
end)
areaSoak.MouseMoved:connect(function(x,y)
if not draggingVertical then return end
local yDelta = y - startYPos
if not control.ScrollDownButton.Visible and yDelta > 0 then
return
end
if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
control.Size = UDim2.new (0,21,0,150)
return
end
startYPos = y
if widgetContainer.Size.Y.Offset + yDelta >= 0 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
end
end)
end
local function switchMinimize()
minimizeFrame.Visible = not minimizeFrame.Visible
if scrollable then
frame.Visible = not frame.Visible
verticalDragger.Visible = not verticalDragger.Visible
control.Visible = not control.Visible
else
widgetContainer.Visible = not widgetContainer.Visible
end
if minimizeFrame.Visible then
minimizeButton.Text = "+"
else
minimizeButton.Text = "-"
end
end
minimizeBigButton.MouseButton1Click:connect(function ( )
switchMinimize()
end)
minimizeButton.MouseButton1Click:connect(function( )
switchMinimize()
end)
if scrollable then
return dragBar, frame, helpFrame, closeEvent
else
return dragBar, widgetContainer, helpFrame, closeEvent
end
end
t.Help =
function(funcNameOrFunc)
--input argument can be a string or a function. Should return a description (of arguments and expected side effects)
if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
return "Function CreatePropertyDropDownMenu. " ..
"Arguments: (instance, propertyName, enumType). " ..
"Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
end
if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
return "Function CreateDropDownMenu. " ..
"Arguments: (items, onItemSelected). " ..
"Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
end
if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
return "Function CreateMessageDialog. " ..
"Arguments: (title, message, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
end
if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
return "Function CreateStyledMessageDialog. " ..
"Arguments: (title, message, style, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
end
if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
return "Function GetFontHeight. " ..
"Arguments: (font, fontSize). " ..
"Side effect: returns the size in pixels of the given font + fontSize"
end
if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
end
if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
return "Function CreateScrollingFrame. " ..
"Arguments: (orderList, style) " ..
"Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
end
if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
return "Function CreateTrueScrollingFrame. " ..
"Arguments: (nil) " ..
"Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
end
if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
return "Function AutoTruncateTextObject. " ..
"Arguments: (textLabel) " ..
"Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
end
if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
return "Function CreateSlider. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then
return "Function CreateSliderNew. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
return "Function CreateLoadingFrame. " ..
"Arguments: (name, size, position) " ..
"Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
end
if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
return "Function CreateTerrainMaterialSelector. " ..
"Arguments: (size, position) " ..
"Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
end
end
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
-- A Few Script Globals
local gui = script.Parent.ControlFrame
local helpButton = nil
local updateCameraDropDownSelection = nil
local updateVideoCaptureDropDownSelection = nil
local tweenTime = 0.2
local mouseLockLookScreenUrl = "http://www.roblox.com/asset?id=54071825"
local classicLookScreenUrl = "http://www.roblox.com/Asset?id=45915798"
local hasGraphicsSlider = true
local GraphicsQualityLevels = 10
local recordingVideo = false
local currentMenuSelection = nil
local lastMenuSelection = {}
local defaultPosition = UDim2.new(0,0,0,0)
local newGuiPlaces = {0,41324860}
local centerDialogs = {}
local mainShield = nil
local inStudioMode = false
local macClient = false
local success, isMac = pcall(function() return not game.GuiService.IsWindows end)
macClient = success and isMac
local function Color3I(r,g,b)
return Color3.new(r/255,g/255,b/255)
end
local function robloxLock(instance)
end
function resumeGameFunction(shield)
shield.Settings:TweenPosition(UDim2.new(0.5, -262,-0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
delay(tweenTime,function()
shield.Visible = false
for i = 1, #centerDialogs do
centerDialogs[i].Visible = false
game.GuiService:RemoveCenterDialog(centerDialogs[i])
end
settingsButton.Active = true
currentMenuSelection = nil
lastMenuSelection = {}
end)
end
function goToMenu(container,menuName, moveDirection,size,position)
if type(menuName) ~= "string" then return end
table.insert(lastMenuSelection,currentMenuSelection)
if menuName == "GameMainMenu" then
lastMenuSelection = {}
end
local containerChildren = container:GetChildren()
local selectedMenu = false
for i = 1, #containerChildren do
if containerChildren[i].Name == menuName then
containerChildren[i].Visible = true
currentMenuSelection = {container = container,name = menuName, direction = moveDirection, lastSize = size}
selectedMenu = true
if size and position then
containerChildren[i]:TweenSizeAndPosition(size,position,Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
elseif size then
containerChildren[i]:TweenSizeAndPosition(size,UDim2.new(0.5,-size.X.Offset/2,0.5,-size.Y.Offset/2),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
else
containerChildren[i]:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
end
else
if moveDirection == "left" then
containerChildren[i]:TweenPosition(UDim2.new(-1,-525,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
elseif moveDirection == "right" then
containerChildren[i]:TweenPosition(UDim2.new(1,525,0,0),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
elseif moveDirection == "up" then
containerChildren[i]:TweenPosition(UDim2.new(0,0,-1,-400),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
elseif moveDirection == "down" then
containerChildren[i]:TweenPosition(UDim2.new(0,0,1,400),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
end
delay(tweenTime,function()
containerChildren[i].Visible = false
end)
end
end
end
function resetLocalCharacter()
local player = game.Players.LocalPlayer
if player then
if player.Character and player.Character:FindFirstChild("Humanoid") then
player.Character.Humanoid.Health = 0
end
end
end
local function createTextButton(text,style,fontSize,buttonSize,buttonPosition)
local newTextButton = Instance.new("TextButton")
newTextButton.Font = Enum.Font.Arial
newTextButton.FontSize = fontSize
newTextButton.Size = buttonSize
newTextButton.Position = buttonPosition
newTextButton.Style = style
newTextButton.TextColor3 = Color3.new(1,1,1)
newTextButton.Text = text
return newTextButton
end
local function CreateTextButtons(frame, buttons, yPos, ySize)
if #buttons < 1 then
error("Must have more than one button")
end
local buttonNum = 1
local buttonObjs = {}
local function toggleSelection(button)
for i, obj in ipairs(buttonObjs) do
if obj == button then
obj.Style = Enum.ButtonStyle.RobloxButtonDefault
else
obj.Style = Enum.ButtonStyle.RobloxButton
end
end
end
for i, obj in ipairs(buttons) do
local button = Instance.new("TextButton")
button.Name = "Button" .. buttonNum
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size18
button.AutoButtonColor = true
button.Style = Enum.ButtonStyle.RobloxButton
button.Text = obj.Text
button.TextColor3 = Color3.new(1,1,1)
button.MouseButton1Click:connect(function() toggleSelection(button) obj.Function() end)
button.Parent = frame
buttonObjs[buttonNum] = button
buttonNum = buttonNum + 1
end
toggleSelection(buttonObjs[1])
local numButtons = buttonNum-1
if numButtons == 1 then
frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
elseif numButtons == 2 then
frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
elseif numButtons >= 3 then
local spacing = .1 / numButtons
local buttonSize = .9 / numButtons
buttonNum = 1
while buttonNum <= numButtons do
buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
buttonNum = buttonNum + 1
end
end
end
function setRecordGui(recording, stopRecordButton, recordVideoButton)
if recording then
stopRecordButton.Visible = true
recordVideoButton.Text = "Stop Recording"
else
stopRecordButton.Visible = false
recordVideoButton.Text = "Record Video"
end
end
function recordVideoClick(recordVideoButton, stopRecordButton)
recordingVideo = not recordingVideo
setRecordGui(recordingVideo, stopRecordButton, recordVideoButton)
end
function backToGame(buttonClicked, shield, settingsButton)
buttonClicked.Parent.Parent.Parent.Parent.Visible = false
shield.Visible = false
for i = 1, #centerDialogs do
game.GuiService:RemoveCenterDialog(centerDialogs[i])
centerDialogs[i].Visible = false
end
centerDialogs = {}
game.GuiService:RemoveCenterDialog(shield)
settingsButton.Active = true
end
function setDisabledState(guiObject)
if not guiObject then return end
if guiObject:IsA("TextLabel") then
guiObject.TextTransparency = 0.9
elseif guiObject:IsA("TextButton") then
guiObject.TextTransparency = 0.9
guiObject.Active = false
else
if guiObject["ClassName"] then
print("setDisabledState() got object of unsupported type. object type is ",guiObject.ClassName)
end
end
end
local function createHelpDialog(baseZIndex)
if helpButton == nil then
if gui:FindFirstChild("TopLeftControl") and gui.TopLeftControl:FindFirstChild("Help") then
helpButton = gui.TopLeftControl.Help
elseif gui:FindFirstChild("BottomRightControl") and gui.BottomRightControl:FindFirstChild("Help") then
helpButton = gui.BottomRightControl.Help
end
end
local shield = Instance.new("Frame")
shield.Name = "HelpDialogShield"
shield.Active = true
shield.Visible = false
shield.Size = UDim2.new(1,0,1,0)
shield.BackgroundColor3 = Color3I(51,51,51)
shield.BorderColor3 = Color3I(27,42,53)
shield.BackgroundTransparency = 0.4
shield.ZIndex = baseZIndex + 1
shield.Parent = gui
local helpDialog = Instance.new("Frame")
helpDialog.Name = "HelpDialog"
helpDialog.Style = Enum.FrameStyle.RobloxRound
helpDialog.Position = UDim2.new(.2, 0, .2, 0)
helpDialog.Size = UDim2.new(0.6, 0, 0.6, 0)
helpDialog.Active = true
helpDialog.Parent = shield
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = "Keyboard & Mouse Controls"
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.Position = UDim2.new(0, 0, 0.025, 0)
titleLabel.Size = UDim2.new(1, 0, 0, 40)
titleLabel.TextColor3 = Color3.new(1,1,1)
titleLabel.BackgroundTransparency = 1
titleLabel.Parent = helpDialog
local buttonRow = Instance.new("Frame")
buttonRow.Name = "Buttons"
buttonRow.Position = UDim2.new(0.1, 0, .07, 40)
buttonRow.Size = UDim2.new(0.8, 0, 0, 45)
buttonRow.BackgroundTransparency = 1
buttonRow.Parent = helpDialog
local imageFrame = Instance.new("Frame")
imageFrame.Name = "ImageFrame"
imageFrame.Position = UDim2.new(0.05, 0, 0.075, 80)
imageFrame.Size = UDim2.new(0.9, 0, .9, -120)
imageFrame.BackgroundTransparency = 1
imageFrame.Parent = helpDialog
local layoutFrame = Instance.new("Frame")
layoutFrame.Name = "LayoutFrame"
layoutFrame.Position = UDim2.new(0.5, 0, 0, 0)
layoutFrame.Size = UDim2.new(1.5, 0, 1, 0)
layoutFrame.BackgroundTransparency = 1
layoutFrame.SizeConstraint = Enum.SizeConstraint.RelativeYY
layoutFrame.Parent = imageFrame
local image = Instance.new("ImageLabel")
image.Name = "Image"
if UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then
image.Image = mouseLockLookScreenUrl
else
image.Image = classicLookScreenUrl
end
image.Position = UDim2.new(-0.5, 0, 0, 0)
image.Size = UDim2.new(1, 0, 1, 0)
image.BackgroundTransparency = 1
image.Parent = layoutFrame
local buttons = {}
buttons[1] = {}
buttons[1].Text = "Look"
buttons[1].Function = function()
if UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then
image.Image = mouseLockLookScreenUrl
else
image.Image = classicLookScreenUrl
end
end
buttons[2] = {}
buttons[2].Text = "Move"
buttons[2].Function = function()
image.Image = "http://www.roblox.com/Asset?id=45915811"
end
buttons[3] = {}
buttons[3].Text = "Gear"
buttons[3].Function = function()
image.Image = "http://www.roblox.com/Asset?id=45917596"
end
buttons[4] = {}
buttons[4].Text = "Zoom"
buttons[4].Function = function()
image.Image = "http://www.roblox.com/Asset?id=45915825"
end
CreateTextButtons(buttonRow, buttons, UDim.new(0, 0), UDim.new(1,0))
-- set up listeners for type of mouse mode, but keep constructing gui at same time
delay(0, function()
waitForChild(gui,"UserSettingsShield")
waitForChild(gui.UserSettingsShield,"Settings")
waitForChild(gui.UserSettingsShield.Settings,"SettingsStyle")
waitForChild(gui.UserSettingsShield.Settings.SettingsStyle, "GameSettingsMenu")
waitForChild(gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu, "CameraField")
waitForChild(gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu.CameraField, "DropDownMenuButton")
gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu.CameraField.DropDownMenuButton.Changed:connect(function(prop)
if prop ~= "Text" then return end
if buttonRow.Button1.Style == Enum.ButtonStyle.RobloxButtonDefault then -- only change if this is the currently selected panel
if gui.UserSettingsShield.Settings.SettingsStyle.GameSettingsMenu.CameraField.DropDownMenuButton.Text == "Classic" then
image.Image = classicLookScreenUrl
else
image.Image = mouseLockLookScreenUrl
end
end
end)
end)
local okBtn = Instance.new("TextButton")
okBtn.Name = "OkBtn"
okBtn.Text = "OK"
okBtn.Modal = true
okBtn.Size = UDim2.new(0.3, 0, 0, 45)
okBtn.Position = UDim2.new(0.35, 0, .975, -50)
okBtn.Font = Enum.Font.Arial
okBtn.FontSize = Enum.FontSize.Size18
okBtn.BackgroundTransparency = 1
okBtn.TextColor3 = Color3.new(1,1,1)
okBtn.Style = Enum.ButtonStyle.RobloxButtonDefault
okBtn.MouseButton1Click:connect(
function()
gui.HelpDialogShield.Visible = false
end)
okBtn.Parent = helpDialog
return shield
end
local function createLeaveConfirmationMenu(baseZIndex,shield)
local frame = Instance.new("Frame")
frame.Name = "LeaveConfirmationMenu"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1,0,1,0)
frame.Position = UDim2.new(0,0,2,400)
frame.ZIndex = baseZIndex + 4
local yesButton = createTextButton("Leave",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,313,0.8,0))
yesButton.Name = "YesButton"
yesButton.ZIndex = baseZIndex + 4
yesButton.Parent = frame
yesButton.Modal = true
yesButton:SetVerb("Exit")
local noButton = createTextButton("Stay",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,90,0.8,0))
noButton.Name = "NoButton"
noButton.Parent = frame
noButton.ZIndex = baseZIndex + 4
noButton.MouseButton1Click:connect(function()
goToMenu(shield.Settings.SettingsStyle,"GameMainMenu","down",UDim2.new(0,525,0,430))
shield.Settings:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
end)
local leaveText = Instance.new("TextLabel")
leaveText.Name = "LeaveText"
leaveText.Text = "Leave this game?"
leaveText.Size = UDim2.new(1,0,0.8,0)
leaveText.TextWrap = true
leaveText.TextColor3 = Color3.new(1,1,1)
leaveText.Font = Enum.Font.ArialBold
leaveText.FontSize = Enum.FontSize.Size36
leaveText.BackgroundTransparency = 1
leaveText.ZIndex = baseZIndex + 4
leaveText.Parent = frame
return frame
end
local function createResetConfirmationMenu(baseZIndex,shield)
local frame = Instance.new("Frame")
frame.Name = "ResetConfirmationMenu"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1,0,1,0)
frame.Position = UDim2.new(0,0,2,400)
frame.ZIndex = baseZIndex + 4
frame.Parent = gui
local yesButton = createTextButton("Reset",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,313,0,299))
yesButton.Name = "YesButton"
yesButton.ZIndex = baseZIndex + 4
yesButton.Parent = frame
yesButton.Modal = true
yesButton.MouseButton1Click:connect(function()
resumeGameFunction(shield)
resetLocalCharacter()
end)
local noButton = createTextButton("Cancel",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,128,0,50),UDim2.new(0,90,0,299))
noButton.Name = "NoButton"
noButton.Parent = frame
noButton.ZIndex = baseZIndex + 4
noButton.MouseButton1Click:connect(function()
goToMenu(shield.Settings.SettingsStyle,"GameMainMenu","down",UDim2.new(0,525,0,430))
shield.Settings:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
end)
local resetCharacterText = Instance.new("TextLabel")
resetCharacterText.Name = "ResetCharacterText"
resetCharacterText.Text = "Are you sure you want to reset your character?"
resetCharacterText.Size = UDim2.new(1,0,0.8,0)
resetCharacterText.TextWrap = true
resetCharacterText.TextColor3 = Color3.new(1,1,1)
resetCharacterText.Font = Enum.Font.ArialBold
resetCharacterText.FontSize = Enum.FontSize.Size36
resetCharacterText.BackgroundTransparency = 1
resetCharacterText.ZIndex = baseZIndex + 4
resetCharacterText.Parent = frame
local fineResetCharacterText = resetCharacterText:Clone()
fineResetCharacterText.Name = "FineResetCharacterText"
fineResetCharacterText.Text = "You will be put back on a spawn point"
fineResetCharacterText.Size = UDim2.new(0,303,0,18)
fineResetCharacterText.Position = UDim2.new(0, 109, 0, 215)
fineResetCharacterText.FontSize = Enum.FontSize.Size18
fineResetCharacterText.Parent = frame
return frame
end
local function createGameMainMenu(baseZIndex, shield)
local gameMainMenuFrame = Instance.new("Frame")
gameMainMenuFrame.Name = "GameMainMenu"
gameMainMenuFrame.BackgroundTransparency = 1
gameMainMenuFrame.Size = UDim2.new(1,0,1,0)
gameMainMenuFrame.ZIndex = baseZIndex + 4
gameMainMenuFrame.Parent = script.Parent.UserSettingsShield.Settings.SettingsStyle
-- GameMainMenu Children
local gameMainMenuTitle = Instance.new("TextLabel")
gameMainMenuTitle.Name = "Title"
gameMainMenuTitle.Text = "Game Menu"
gameMainMenuTitle.BackgroundTransparency = 1
gameMainMenuTitle.TextStrokeTransparency = 0
gameMainMenuTitle.Font = Enum.Font.ArialBold
gameMainMenuTitle.FontSize = Enum.FontSize.Size36
gameMainMenuTitle.Size = UDim2.new(1,0,0,36)
gameMainMenuTitle.Position = UDim2.new(0,0,0,4)
gameMainMenuTitle.TextColor3 = Color3.new(1,1,1)
gameMainMenuTitle.ZIndex = baseZIndex + 4
gameMainMenuTitle.Parent = gameMainMenuFrame
local robloxHelpButton = createTextButton("Help",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,164,0,50),UDim2.new(0,82,0,256))
robloxHelpButton.Name = "HelpButton"
robloxHelpButton.ZIndex = baseZIndex + 4
robloxHelpButton.Parent = gameMainMenuFrame
helpButton = robloxHelpButton
local helpDialog = createHelpDialog(baseZIndex)
helpDialog.Parent = gui
helpButton.MouseButton1Click:connect(
function()
helpDialog.Visible = true
mainShield.Visible = false
end)
helpButton.Active = true
local helpShortcut = Instance.new("TextLabel")
helpShortcut.Name = "HelpShortcutText"
helpShortcut.Text = "F1"
helpShortcut.Visible = false
helpShortcut.BackgroundTransparency = 1
helpShortcut.Font = Enum.Font.Arial
helpShortcut.FontSize = Enum.FontSize.Size12
helpShortcut.Position = UDim2.new(0,85,0,0)
helpShortcut.Size = UDim2.new(0,30,0,30)
helpShortcut.TextColor3 = Color3.new(0,1,0)
helpShortcut.ZIndex = baseZIndex + 4
helpShortcut.Parent = robloxHelpButton
local screenshotButton = createTextButton("Screenshot",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,168,0,50),UDim2.new(0,254,0,256))
screenshotButton.Name = "ScreenshotButton"
screenshotButton.ZIndex = baseZIndex + 4
screenshotButton.Parent = shield.Settings.SettingsStyle.GameMainMenu
screenshotButton.Visible = not macClient
screenshotButton:SetVerb("Screenshot")
local screenshotShortcut = helpShortcut:clone()
screenshotShortcut.Name = "ScreenshotShortcutText"
screenshotShortcut.Text = "PrintSc"
screenshotShortcut.Position = UDim2.new(0,118,0,0)
screenshotShortcut.Visible = true
screenshotShortcut.Parent = screenshotButton
local recordVideoButton = createTextButton("Record Video",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,168,0,50),UDim2.new(0,254,0,306))
recordVideoButton.Name = "RecordVideoButton"
recordVideoButton.ZIndex = baseZIndex + 4
recordVideoButton.Parent = gameMainMenuFrame
recordVideoButton.Visible = not macClient
recordVideoButton:SetVerb("RecordToggle")
local recordVideoShortcut = helpShortcut:clone()
recordVideoShortcut.Visible = hasGraphicsSlider
recordVideoShortcut.Name = "RecordVideoShortcutText"
recordVideoShortcut.Text = "F12"
recordVideoShortcut.Position = UDim2.new(0,120,0,0)
recordVideoShortcut.Parent = recordVideoButton
local stopRecordButton = Instance.new("ImageButton")
stopRecordButton.Name = "StopRecordButton"
stopRecordButton.BackgroundTransparency = 1
stopRecordButton.Image = "rbxasset://textures/ui/RecordStop.png"
stopRecordButton.Size = UDim2.new(0,59,0,27)
stopRecordButton:SetVerb("RecordToggle")
stopRecordButton.MouseButton1Click:connect(function() stopRecordButton.Visible = false end)
recordVideoButton.MouseButton1Click:connect(function() stopRecordButton.Visible = true game.Players.LocalPlayer.PlayerGui.Menu.UserSettingsShield.Visible = false end)
stopRecordButton.Visible = false
stopRecordButton.Parent = gui
local reportAbuseButton = createTextButton("Report Abuse",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,164,0,50),UDim2.new(0,82,0,306))
reportAbuseButton.Name = "ReportAbuseButton"
reportAbuseButton.ZIndex = baseZIndex + 4
reportAbuseButton.Parent = gameMainMenuFrame
reportAbuseButton.Active = true
local leaveGameButton = createTextButton("Leave Game",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,358))
leaveGameButton.Name = "LeaveGameButton"
leaveGameButton.ZIndex = baseZIndex + 4
leaveGameButton.Parent = gameMainMenuFrame
local resumeGameButton = createTextButton("Resume Game",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,54))
resumeGameButton.Name = "resumeGameButton"
resumeGameButton.ZIndex = baseZIndex + 4
resumeGameButton.Parent = gameMainMenuFrame
resumeGameButton.Modal = true
resumeGameButton.MouseButton1Click:connect(function() resumeGameFunction(shield) end)
local gameSettingsButton = createTextButton("Game Settings",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,156))
gameSettingsButton.Name = "SettingsButton"
gameSettingsButton.ZIndex = baseZIndex + 4
gameSettingsButton.Parent = gameMainMenuFrame
if game:FindFirstChild("LoadingGuiService") and #game.LoadingGuiService:GetChildren() > 0 then
local gameSettingsButton = createTextButton("Game Instructions",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,207))
gameSettingsButton.Name = "GameInstructions"
gameSettingsButton.ZIndex = baseZIndex + 4
gameSettingsButton.Parent = gameMainMenuFrame
gameSettingsButton.MouseButton1Click:connect(function()
if game:FindFirstChild("Players") and game.Players["LocalPlayer"] then
local loadingGui = game.Players.LocalPlayer:FindFirstChild("PlayerLoadingGui")
if loadingGui then
loadingGui.Visible = true
end
end
end)
end
local resetButton = createTextButton("Reset Character",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size24,UDim2.new(0,340,0,50),UDim2.new(0,82,0,105))
resetButton.Name = "ResetButton"
resetButton.ZIndex = baseZIndex + 4
resetButton.Parent = gameMainMenuFrame
return gameMainMenuFrame
end
local function createGameSettingsMenu(baseZIndex, shield)
local gameSettingsMenuFrame = Instance.new("Frame")
gameSettingsMenuFrame.Name = "GameSettingsMenu"
gameSettingsMenuFrame.BackgroundTransparency = 1
gameSettingsMenuFrame.Size = UDim2.new(1,0,1,0)
gameSettingsMenuFrame.ZIndex = baseZIndex + 4
local title = Instance.new("TextLabel")
title.Name = "Title"
title.Text = "Settings"
title.Size = UDim2.new(1,0,0,48)
title.Position = UDim2.new(0,9,0,-9)
title.Font = Enum.Font.ArialBold
title.FontSize = Enum.FontSize.Size36
title.TextColor3 = Color3.new(1,1,1)
title.ZIndex = baseZIndex + 4
title.BackgroundTransparency = 1
title.Parent = gameSettingsMenuFrame
--[[
local studioText = Instance.new("TextLabel")
studioText.Visible = false
studioText.Name = "StudioText"
studioText.Text = "Studio Mode"
studioText.Size = UDim2.new(0,95,0,18)
studioText.Position = UDim2.new(0,62,0,179)
studioText.Font = Enum.Font.Arial
studioText.FontSize = Enum.FontSize.Size18
studioText.TextColor3 = Color3.new(1,1,1)
studioText.ZIndex = baseZIndex + 4
studioText.BackgroundTransparency = 1
studioText.Parent = gameSettingsMenuFrame
local studioShortcut = fullscreenShortcut:clone()
studioShortcut.Name = "StudioShortcutText"
studioShortcut.Visible = false -- TODO: turn back on when f2 hack is fixed
studioShortcut.Text = "F2"
studioShortcut.Position = UDim2.new(0,154,0,175)
studioShortcut.Parent = gameSettingsMenuFrame
local studioCheckbox = nil
--]]
local itemTop = 35
----------------------------------------------------------------------------------------------------
-- C A M E R A C O N T R O L S
----------------------------------------------------------------------------------------------------
if not touchClient then
local cameraLabel = Instance.new("TextLabel")
cameraLabel.Name = "CameraLabel"
cameraLabel.Text = "Character & Camera Controls"
cameraLabel.Font = Enum.Font.Arial
cameraLabel.FontSize = Enum.FontSize.Size18
cameraLabel.Position = UDim2.new(0,31,0,itemTop + 6)
cameraLabel.Size = UDim2.new(0,224,0,18)
cameraLabel.TextColor3 = Color3I(255,255,255)
cameraLabel.TextXAlignment = Enum.TextXAlignment.Left
cameraLabel.BackgroundTransparency = 1
cameraLabel.ZIndex = baseZIndex + 4
cameraLabel.Parent = gameSettingsMenuFrame
local mouseLockLabel = nil
local enumItems = Enum.ControlMode:GetEnumItems()
local enumNames = {}
local enumNameToItem = {}
for i,obj in ipairs(enumItems) do
enumNames[i] = obj.Name
enumNameToItem[obj.Name] = obj
end
local cameraDropDown
cameraDropDown, updateCameraDropDownSelection = RbxGui.CreateDropDownMenu(enumNames,
function(text)
UserSettings().GameSettings.ControlMode = enumNameToItem[text]
pcall(function()
if mouseLockLabel and UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then
mouseLockLabel.Visible = true
elseif mouseLockLabel then
mouseLockLabel.Visible = false
end
end)
end)
cameraDropDown.Name = "CameraField"
cameraDropDown.ZIndex = baseZIndex + 4
cameraDropDown.DropDownMenuButton.ZIndex = baseZIndex + 4
cameraDropDown.DropDownMenuButton.Icon.ZIndex = baseZIndex + 4
cameraDropDown.Position = UDim2.new(0, 270, 0, itemTop)
cameraDropDown.Size = UDim2.new(0,200,0,32)
cameraDropDown.Parent = gameSettingsMenuFrame
itemTop = itemTop + 35
end
----------------------------------------------------------------------------------------------------
-- V I D E O C A P T U R E S E T T I N G S
----------------------------------------------------------------------------------------------------
local syncVideoCaptureSetting = nil
if not macClient and not touchClient then
local videoCaptureLabel = Instance.new("TextLabel")
videoCaptureLabel.Name = "VideoCaptureLabel"
videoCaptureLabel.Text = "After Capturing Video"
videoCaptureLabel.Font = Enum.Font.Arial
videoCaptureLabel.FontSize = Enum.FontSize.Size18
videoCaptureLabel.Position = UDim2.new(0,32,0,itemTop + 6)
videoCaptureLabel.Size = UDim2.new(0,164,0,18)
videoCaptureLabel.BackgroundTransparency = 1
videoCaptureLabel.TextColor3 = Color3I(255,255,255)
videoCaptureLabel.TextXAlignment = Enum.TextXAlignment.Left
videoCaptureLabel.ZIndex = baseZIndex + 4
videoCaptureLabel.Parent = gameSettingsMenuFrame
local videoNames = {}
local videoNameToItem = {}
videoNames[1] = "Just Save to Disk"
videoNameToItem[videoNames[1]] = Enum.UploadSetting["Never"]
videoNames[2] = "Upload to YouTube"
videoNameToItem[videoNames[2]] = Enum.UploadSetting["Ask me first"]
local videoCaptureDropDown = nil
videoCaptureDropDown, updateVideoCaptureDropDownSelection = RbxGui.CreateDropDownMenu(videoNames,
function(text)
UserSettings().GameSettings.VideoUploadPromptBehavior = videoNameToItem[text]
end)
videoCaptureDropDown.Name = "VideoCaptureField"
videoCaptureDropDown.ZIndex = baseZIndex + 4
videoCaptureDropDown.DropDownMenuButton.ZIndex = baseZIndex + 4
videoCaptureDropDown.DropDownMenuButton.Icon.ZIndex = baseZIndex + 4
videoCaptureDropDown.Position = UDim2.new(0, 270, 0, itemTop)
videoCaptureDropDown.Size = UDim2.new(0,200,0,32)
videoCaptureDropDown.Parent = gameSettingsMenuFrame
syncVideoCaptureSetting = function()
if UserSettings().GameSettings.VideoUploadPromptBehavior == Enum.UploadSetting["Never"] then
updateVideoCaptureDropDownSelection(videoNames[1])
elseif UserSettings().GameSettings.VideoUploadPromptBehavior == Enum.UploadSetting["Ask me first"] then
updateVideoCaptureDropDownSelection(videoNames[2])
else
UserSettings().GameSettings.VideoUploadPromptBehavior = Enum.UploadSetting["Ask me first"]
updateVideoCaptureDropDownSelection(videoNames[2])
end
end
itemTop = itemTop + 35
end
----------------------------------------------------------------------------------------------------
-- C U S T O M C A M E R A C O N T R O L S
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- F U L L S C R E E N M O D E
----------------------------------------------------------------------------------------------------
local fullscreenText = nil
local fullscreenShortcut = nil
local fullscreenCheckbox = nil
if not touchClient then
fullscreenText = Instance.new("TextLabel")
fullscreenText.Name = "FullscreenText"
fullscreenText.Text = "Fullscreen Mode"
fullscreenText.Size = UDim2.new(0,124,0,18)
fullscreenText.Position = UDim2.new(0,62,0,itemTop + 2)
fullscreenText.Font = Enum.Font.Arial
fullscreenText.FontSize = Enum.FontSize.Size18
fullscreenText.TextColor3 = Color3.new(1,1,1)
fullscreenText.ZIndex = baseZIndex + 4
fullscreenText.BackgroundTransparency = 1
fullscreenText.Parent = gameSettingsMenuFrame
fullscreenShortcut = Instance.new("TextLabel")
fullscreenShortcut.Visible = hasGraphicsSlider
fullscreenShortcut.Name = "FullscreenShortcutText"
fullscreenShortcut.Text = "F11"
fullscreenShortcut.BackgroundTransparency = 1
fullscreenShortcut.Font = Enum.Font.Arial
fullscreenShortcut.FontSize = Enum.FontSize.Size12
fullscreenShortcut.Position = UDim2.new(0,186,0,itemTop - 4)
fullscreenShortcut.Size = UDim2.new(0,30,0,30)
fullscreenShortcut.TextColor3 = Color3.new(0,1,0)
fullscreenShortcut.ZIndex = baseZIndex + 4
fullscreenShortcut.Parent = gameSettingsMenuFrame
fullscreenCheckbox = createTextButton("",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,25,0,25),UDim2.new(0,30,0,itemTop))
fullscreenCheckbox.Name = "FullscreenCheckbox"
fullscreenCheckbox.ZIndex = baseZIndex + 4
fullscreenCheckbox.Parent = gameSettingsMenuFrame
fullscreenCheckbox:SetVerb("ToggleFullScreen")
if UserSettings().GameSettings:InFullScreen() then fullscreenCheckbox.Text = "X" end
if hasGraphicsSlider then
UserSettings().GameSettings.FullscreenChanged:connect(function(isFullscreen)
if isFullscreen then
fullscreenCheckbox.Text = "X"
else
fullscreenCheckbox.Text = ""
end
end)
else
fullscreenCheckbox.MouseButton1Click:connect(function()
if fullscreenCheckbox.Text == "" then
fullscreenCheckbox.Text = "X"
else
fullscreenCheckbox.Text = ""
end
end)
end
end
----------------------------------------------------------------------------------------------------
-- G R A P H I C S S L I D E R
----------------------------------------------------------------------------------------------------
if hasGraphicsSlider then
local qualityText = Instance.new("TextLabel")
qualityText.Name = "QualityText"
qualityText.Text = "Graphics Quality"
qualityText.Size = UDim2.new(0,128,0,18)
qualityText.Position = UDim2.new(0,30,0,239)
qualityText.Font = Enum.Font.Arial
qualityText.FontSize = Enum.FontSize.Size18
qualityText.TextColor3 = Color3.new(1,1,1)
qualityText.ZIndex = baseZIndex + 4
qualityText.BackgroundTransparency = 1
qualityText.Parent = gameSettingsMenuFrame
qualityText.Visible = not inStudioMode
local autoText = qualityText:clone()
autoText.Name = "AutoText"
autoText.Text = "Auto"
autoText.Position = UDim2.new(0,183,0,214)
autoText.TextColor3 = Color3.new(128/255,128/255,128/255)
autoText.Size = UDim2.new(0,34,0,18)
autoText.Parent = gameSettingsMenuFrame
autoText.Visible = not inStudioMode
local fasterText = autoText:clone()
fasterText.Name = "FasterText"
fasterText.Text = "Faster"
fasterText.Position = UDim2.new(0,185,0,274)
fasterText.TextColor3 = Color3.new(95,95,95)
fasterText.FontSize = Enum.FontSize.Size14
fasterText.Parent = gameSettingsMenuFrame
fasterText.Visible = not inStudioMode
local fasterShortcut = fullscreenShortcut:clone()
fasterShortcut.Name = "FasterShortcutText"
fasterShortcut.Text = "F10 + Shift"
fasterShortcut.Position = UDim2.new(0,185,0,283)
fasterShortcut.Parent = gameSettingsMenuFrame
fasterShortcut.Visible = not inStudioMode
local betterQualityText = autoText:clone()
betterQualityText.Name = "BetterQualityText"
betterQualityText.Text = "Better Quality"
betterQualityText.TextWrap = true
betterQualityText.Size = UDim2.new(0,41,0,28)
betterQualityText.Position = UDim2.new(0,390,0,269)
betterQualityText.TextColor3 = Color3.new(95,95,95)
betterQualityText.FontSize = Enum.FontSize.Size14
betterQualityText.Parent = gameSettingsMenuFrame
betterQualityText.Visible = not inStudioMode
local betterQualityShortcut = fullscreenShortcut:clone()
betterQualityShortcut.Name = "BetterQualityShortcut"
betterQualityShortcut.Text = "F10"
betterQualityShortcut.Position = UDim2.new(0,394,0,288)
betterQualityShortcut.Parent = gameSettingsMenuFrame
betterQualityShortcut.Visible = not inStudioMode
local autoGraphicsButton = createTextButton("X",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,25,0,25),UDim2.new(0,187,0,239))
autoGraphicsButton.Name = "AutoGraphicsButton"
autoGraphicsButton.ZIndex = baseZIndex + 4
autoGraphicsButton.Parent = gameSettingsMenuFrame
autoGraphicsButton.Visible = not inStudioMode
local graphicsSlider, graphicsLevel = RbxGui.CreateSlider(GraphicsQualityLevels,150,UDim2.new(0, 230, 0, 280)) -- graphics - 1 because slider starts at 1 instead of 0
graphicsSlider.Parent = gameSettingsMenuFrame
graphicsSlider.Bar.ZIndex = baseZIndex + 4
graphicsSlider.Bar.Slider.ZIndex = baseZIndex + 5
graphicsSlider.Visible = not inStudioMode
graphicsLevel.Value = math.floor((settings().Rendering:GetMaxQualityLevel() - 1)/2)
local graphicsSetter = Instance.new("TextBox")
graphicsSetter.Name = "GraphicsSetter"
graphicsSetter.BackgroundColor3 = Color3.new(0,0,0)
graphicsSetter.BorderColor3 = Color3.new(128/255,128/255,128/255)
graphicsSetter.Size = UDim2.new(0,50,0,25)
graphicsSetter.Position = UDim2.new(0,450,0,269)
graphicsSetter.TextColor3 = Color3.new(1,1,1)
graphicsSetter.Font = Enum.Font.Arial
graphicsSetter.FontSize = Enum.FontSize.Size18
graphicsSetter.Text = "Auto"
graphicsSetter.ZIndex = 1
graphicsSetter.TextWrap = true
graphicsSetter.Parent = gameSettingsMenuFrame
graphicsSetter.Visible = not inStudioMode
local isAutoGraphics = true
if not inStudioMode then
isAutoGraphics = (UserSettings().GameSettings.SavedQualityLevel == Enum.SavedQualitySetting.Automatic)
else
settings().Rendering.EnableFRM = false
end
local listenToGraphicsLevelChange = true
local function setAutoGraphicsGui(active)
isAutoGraphics = active
if active then
autoGraphicsButton.Text = "X"
betterQualityText.ZIndex = 1
betterQualityShortcut.ZIndex = 1
fasterShortcut.ZIndex = 1
fasterText.ZIndex = 1
graphicsSlider.Bar.ZIndex = 1
graphicsSlider.Bar.Slider.ZIndex = 1
graphicsSetter.ZIndex = 1
graphicsSetter.Text = "Auto"
else
autoGraphicsButton.Text = ""
graphicsSlider.Bar.ZIndex = baseZIndex + 4
graphicsSlider.Bar.Slider.ZIndex = baseZIndex + 5
betterQualityShortcut.ZIndex = baseZIndex + 4
fasterShortcut.ZIndex = baseZIndex + 4
betterQualityText.ZIndex = baseZIndex + 4
fasterText.ZIndex = baseZIndex + 4
graphicsSetter.ZIndex = baseZIndex + 4
end
end
local function goToAutoGraphics()
setAutoGraphicsGui(true)
UserSettings().GameSettings.SavedQualityLevel = Enum.SavedQualitySetting.Automatic
settings().Rendering.QualityLevel = Enum.QualityLevel.Automatic
end
local function setGraphicsQualityLevel(newLevel)
local percentage = newLevel/GraphicsQualityLevels
local newSetting = math.floor((settings().Rendering:GetMaxQualityLevel() - 1) * percentage)
if newSetting == 20 then -- Level 20 is the same as level 21, except it doesn't render ambient occlusion
newSetting = 21
elseif newLevel == 1 then -- make sure we can go to lowest settings (for terrible computers)
newSetting = 1
elseif newSetting > settings().Rendering:GetMaxQualityLevel() then
newSetting = settings().Rendering:GetMaxQualityLevel() - 1
end
UserSettings().GameSettings.SavedQualityLevel = newLevel
settings().Rendering.QualityLevel = newSetting
end
local function goToManualGraphics(explicitLevel)
setAutoGraphicsGui(false)
if explicitLevel then
graphicsLevel.Value = explicitLevel
else
graphicsLevel.Value = math.floor((settings().Rendering.AutoFRMLevel/(settings().Rendering:GetMaxQualityLevel() - 1)) * GraphicsQualityLevels)
end
if explicitLevel == graphicsLevel.Value then -- make sure we are actually in right graphics mode
setGraphicsQualityLevel(graphicsLevel.Value)
end
if not explicitLevel then
UserSettings().GameSettings.SavedQualityLevel = graphicsLevel.Value
end
graphicsSetter.Text = tostring(graphicsLevel.Value)
end
local function showAutoGraphics()
autoText.ZIndex = baseZIndex + 4
autoGraphicsButton.ZIndex = baseZIndex + 4
end
local function hideAutoGraphics()
autoText.ZIndex = 1
autoGraphicsButton.ZIndex = 1
end
local function showManualGraphics()
graphicsSlider.Bar.ZIndex = baseZIndex + 4
graphicsSlider.Bar.Slider.ZIndex = baseZIndex + 5
betterQualityShortcut.ZIndex = baseZIndex + 4
fasterShortcut.ZIndex = baseZIndex + 4
betterQualityText.ZIndex = baseZIndex + 4
fasterText.ZIndex = baseZIndex + 4
graphicsSetter.ZIndex = baseZIndex + 4
end
local function hideManualGraphics()
betterQualityText.ZIndex = 1
betterQualityShortcut.ZIndex = 1
fasterShortcut.ZIndex = 1
fasterText.ZIndex = 1
graphicsSlider.Bar.ZIndex = 1
graphicsSlider.Bar.Slider.ZIndex = 1
graphicsSetter.ZIndex = 1
end
local function translateSavedQualityLevelToInt(savedQualityLevel)
if savedQualityLevel == Enum.SavedQualitySetting.Automatic then
return 0
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel1 then
return 1
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel2 then
return 2
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel3 then
return 3
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel4 then
return 4
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel5 then
return 5
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel6 then
return 6
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel7 then
return 7
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel8 then
return 8
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel9 then
return 9
elseif savedQualityLevel == Enum.SavedQualitySetting.QualityLevel10 then
return 10
end
end
local function enableGraphicsWidget()
settings().Rendering.EnableFRM = true
isAutoGraphics = (UserSettings().GameSettings.SavedQualityLevel == Enum.SavedQualitySetting.Automatic)
if isAutoGraphics then
showAutoGraphics()
goToAutoGraphics()
else
showAutoGraphics()
showManualGraphics()
goToManualGraphics(translateSavedQualityLevelToInt(UserSettings().GameSettings.SavedQualityLevel))
end
end
local function disableGraphicsWidget()
hideManualGraphics()
hideAutoGraphics()
settings().Rendering.EnableFRM = false
end
graphicsSetter.FocusLost:connect(function()
if isAutoGraphics then
graphicsSetter.Text = tostring(graphicsLevel.Value)
return
end
local newGraphicsValue = tonumber(graphicsSetter.Text)
if newGraphicsValue == nil then
graphicsSetter.Text = tostring(graphicsLevel.Value)
return
end
if newGraphicsValue < 1 then newGraphicsValue = 1
elseif newGraphicsValue >= settings().Rendering:GetMaxQualityLevel() then
newGraphicsValue = settings().Rendering:GetMaxQualityLevel() - 1
end
graphicsLevel.Value = newGraphicsValue
setGraphicsQualityLevel(graphicsLevel.Value)
graphicsSetter.Text = tostring(graphicsLevel.Value)
end)
graphicsLevel.Changed:connect(function(prop)
if isAutoGraphics then return end
if not listenToGraphicsLevelChange then return end
graphicsSetter.Text = tostring(graphicsLevel.Value)
setGraphicsQualityLevel(graphicsLevel.Value)
end)
-- setup our graphic mode on load
if inStudioMode or UserSettings().GameSettings.SavedQualityLevel == Enum.SavedQualitySetting.Automatic then
if inStudioMode then
settings().Rendering.EnableFRM = false
disableGraphicsWidget()
else
settings().Rendering.EnableFRM = true
goToAutoGraphics()
end
else
settings().Rendering.EnableFRM = true
goToManualGraphics(translateSavedQualityLevelToInt(UserSettings().GameSettings.SavedQualityLevel))
end
autoGraphicsButton.MouseButton1Click:connect(function()
if inStudioMode and not game.Players.LocalPlayer then return end
if not isAutoGraphics then
goToAutoGraphics()
else
goToManualGraphics(graphicsLevel.Value)
end
end)
local lastUpdate = nil
game.GraphicsQualityChangeRequest:connect(function(graphicsIncrease)
if isAutoGraphics then return end -- only can set graphics in manual mode
if graphicsIncrease then
if (graphicsLevel.Value + 1) > GraphicsQualityLevels then return end
graphicsLevel.Value = graphicsLevel.Value + 1
graphicsSetter.Text = tostring(graphicsLevel.Value)
setGraphicsQualityLevel(graphicsLevel.Value)
game:GetService("GuiService"):SendNotification("Graphics Quality",
"Increased to (" .. graphicsSetter.Text .. ")",
"",
2,
function()
end)
else
if (graphicsLevel.Value - 1) <= 0 then return end
graphicsLevel.Value = graphicsLevel.Value - 1
graphicsSetter.Text = tostring(graphicsLevel.Value)
setGraphicsQualityLevel(graphicsLevel.Value)
game:GetService("GuiService"):SendNotification("Graphics Quality",
"Decreased to (" .. graphicsSetter.Text .. ")",
"",
2,
function()
end)
end
end)
game.Players.PlayerAdded:connect(function(player)
if player == game.Players.LocalPlayer and inStudioMode then
enableGraphicsWidget()
end
end)
game.Players.PlayerRemoving:connect(function(player)
if player == game.Players.LocalPlayer and inStudioMode then
disableGraphicsWidget()
end
end)
studioCheckbox = createTextButton("",Enum.ButtonStyle.RobloxButton,Enum.FontSize.Size18,UDim2.new(0,25,0,25),UDim2.new(0,30,0,176))
studioCheckbox.Name = "StudioCheckbox"
studioCheckbox.ZIndex = baseZIndex + 4
--studioCheckbox.Parent = gameSettingsMenuFrame -- todo: enable when studio h4x aren't an issue anymore
studioCheckbox:SetVerb("TogglePlayMode")
studioCheckbox.Visible = false -- todo: enabled when studio h4x aren't an issue anymore
local wasManualGraphics = (settings().Rendering.QualityLevel ~= Enum.QualityLevel.Automatic)
if inStudioMode and not game.Players.LocalPlayer then
studioCheckbox.Text = "X"
disableGraphicsWidget()
elseif inStudioMode then
studioCheckbox.Text = "X"
enableGraphicsWidget()
end
if hasGraphicsSlider then
UserSettings().GameSettings.StudioModeChanged:connect(function(isStudioMode)
inStudioMode = isStudioMode
if isStudioMode then
wasManualGraphics = (settings().Rendering.QualityLevel ~= Enum.QualityLevel.Automatic)
goToAutoGraphics()
studioCheckbox.Text = "X"
autoGraphicsButton.ZIndex = 1
autoText.ZIndex = 1
else
if wasManualGraphics then
goToManualGraphics()
end
studioCheckbox.Text = ""
autoGraphicsButton.ZIndex = baseZIndex + 4
autoText.ZIndex = baseZIndex + 4
end
end)
else
studioCheckbox.MouseButton1Click:connect(function()
if not studioCheckbox.Active then return end
if studioCheckbox.Text == "" then
studioCheckbox.Text = "X"
else
studioCheckbox.Text = ""
end
end)
end
end
if game:FindFirstChild("NetworkClient") then -- we are playing online
setDisabledState(studioText)
setDisabledState(studioShortcut)
setDisabledState(studioCheckbox)
end
----------------------------------------------------------------------------------------------------
-- O K B U T T O N
----------------------------------------------------------------------------------------------------
local backButton
if hasGraphicsSlider then
backButton = createTextButton("OK",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,180,0,50),UDim2.new(0,170,0,330))
backButton.Modal = true
else
backButton = createTextButton("OK",Enum.ButtonStyle.RobloxButtonDefault,Enum.FontSize.Size24,UDim2.new(0,180,0,50),UDim2.new(0,170,0,270))
backButton.Modal = true
end
backButton.Name = "BackButton"
backButton.ZIndex = baseZIndex + 4
backButton.Parent = gameSettingsMenuFrame
return gameSettingsMenuFrame
end
if LoadLibrary then
RbxGui = t
local baseZIndex = 0
if UserSettings then
local createReportAbuseDialog = function()
waitForChild(game,"Players")
waitForProperty(game.Players, "LocalPlayer")
local localPlayer = game.Players.LocalPlayer
local reportAbuseButton
waitForChild(script.Parent,"UserSettingsShield")
waitForChild(script.Parent.UserSettingsShield, "Settings")
waitForChild(script.Parent.UserSettingsShield.Settings,"SettingsStyle")
waitForChild(script.Parent.UserSettingsShield.Settings.SettingsStyle,"GameMainMenu")
waitForChild(script.Parent.UserSettingsShield.Settings.SettingsStyle.GameMainMenu, "ReportAbuseButton")
reportAbuseButton = script.Parent.UserSettingsShield.Settings.SettingsStyle.GameMainMenu.ReportAbuseButton
local shield = Instance.new("TextButton")
shield.Name = "ReportAbuseShield"
shield.Text = ""
shield.AutoButtonColor = false
shield.Active = true
shield.Visible = false
shield.Size = UDim2.new(1,0,1,0)
shield.BackgroundColor3 = Color3I(51,51,51)
shield.BorderColor3 = Color3I(27,42,53)
shield.BackgroundTransparency = 0.4
shield.ZIndex = baseZIndex + 1
local closeAndResetDialgo
local messageBoxButtons = {}
messageBoxButtons[1] = {}
messageBoxButtons[1].Text = "Ok"
messageBoxButtons[1].Modal = true
messageBoxButtons[1].Function = function() closeAndResetDialog() end
local calmingMessageBox = RbxGui.CreateMessageDialog("Thanks for your report!", "Our moderators will review the chat logs and determine what happened. The other user is probably just trying to make you mad.\n\nIf anyone used swear words, inappropriate language, or threatened you in real life, please report them for Bad Words or Threats", messageBoxButtons)
calmingMessageBox.Visible = false
calmingMessageBox.Parent = shield
local recordedMessageBox = RbxGui.CreateMessageDialog("Thanks for your report!","We've recorded your report for evaluation.", messageBoxButtons)
recordedMessageBox.Visible = false
recordedMessageBox.Parent = shield
local normalMessageBox = RbxGui.CreateMessageDialog("Thanks for your report!", "Our moderators will review the chat logs and determine what happened.", messageBoxButtons)
normalMessageBox.Visible = false
normalMessageBox.Parent = shield
local frame = Instance.new("Frame")
frame.Name = "Settings"
frame.Position = UDim2.new(0.5, -250, 0.5, -200)
frame.Size = UDim2.new(0.0, 500, 0.0, 400)
frame.BackgroundTransparency = 1
frame.Active = true
frame.Parent = shield
local settingsFrame = Instance.new("Frame")
settingsFrame.Name = "ReportAbuseStyle"
settingsFrame.Size = UDim2.new(1, 0, 1, 0)
settingsFrame.Style = Enum.FrameStyle.RobloxRound
settingsFrame.Active = true
settingsFrame.ZIndex = baseZIndex + 1
settingsFrame.Parent = frame
local title = Instance.new("TextLabel")
title.Name = "Title"
title.Text = "Report Abuse"
title.TextColor3 = Color3I(221,221,221)
title.Position = UDim2.new(0.5, 0, 0, 30)
title.Font = Enum.Font.ArialBold
title.FontSize = Enum.FontSize.Size36
title.ZIndex = baseZIndex + 2
title.Parent = settingsFrame
local description = Instance.new("TextLabel")
description.Name = "Description"
description.Text = "This will send a complete report to a moderator. The moderator will review the chat log and take appropriate action."
description.TextColor3 = Color3I(221,221,221)
description.Position = UDim2.new(0, 0, 0, 55)
description.Size = UDim2.new(1, 0, 0, 40)
description.BackgroundTransparency = 1
description.Font = Enum.Font.Arial
description.FontSize = Enum.FontSize.Size18
description.TextWrap = true
description.ZIndex = baseZIndex + 2
description.TextXAlignment = Enum.TextXAlignment.Left
description.TextYAlignment = Enum.TextYAlignment.Top
description.Parent = settingsFrame
local playerLabel = Instance.new("TextLabel")
playerLabel.Name = "PlayerLabel"
playerLabel.Text = "Which player?"
playerLabel.BackgroundTransparency = 1
playerLabel.Font = Enum.Font.Arial
playerLabel.FontSize = Enum.FontSize.Size18
playerLabel.Position = UDim2.new(0.025,0,0,100)
playerLabel.Size = UDim2.new(0.4,0,0,36)
playerLabel.TextColor3 = Color3I(255,255,255)
playerLabel.TextXAlignment = Enum.TextXAlignment.Left
playerLabel.ZIndex = baseZIndex + 2
playerLabel.Parent = settingsFrame
local abusingPlayer = nil
local abuse = nil
local submitReportButton = nil
local updatePlayerSelection = nil
local createPlayersDropDown = function()
local players = game:GetService("Players")
local playerNames = {}
local nameToPlayer = {}
local children = players:GetChildren()
local pos = 1
if children then
for i, player in ipairs(children) do
if player:IsA("Player") and player ~= localPlayer then
playerNames[pos] = player.Name
nameToPlayer[player.Name] = player
pos = pos + 1
end
end
end
local playerDropDown = nil
playerDropDown, updatePlayerSelection = RbxGui.CreateDropDownMenu(playerNames,
function(playerName)
abusingPlayer = nameToPlayer[playerName]
if abuse and abusingPlayer then
submitReportButton.Active = true
end
end)
playerDropDown.Name = "PlayersComboBox"
playerDropDown.ZIndex = baseZIndex + 2
playerDropDown.Position = UDim2.new(.425, 0, 0, 102)
playerDropDown.Size = UDim2.new(.55,0,0,32)
return playerDropDown
end
local abuseLabel = Instance.new("TextLabel")
abuseLabel.Name = "AbuseLabel"
abuseLabel.Text = "Type of Abuse:"
abuseLabel.Font = Enum.Font.Arial
abuseLabel.BackgroundTransparency = 1
abuseLabel.FontSize = Enum.FontSize.Size18
abuseLabel.Position = UDim2.new(0.025,0,0,140)
abuseLabel.Size = UDim2.new(0.4,0,0,36)
abuseLabel.TextColor3 = Color3I(255,255,255)
abuseLabel.TextXAlignment = Enum.TextXAlignment.Left
abuseLabel.ZIndex = baseZIndex + 2
abuseLabel.Parent = settingsFrame
local abuses = {"Swearing","Bullying","Scamming","Dating","Cheating/Exploiting","Personal Questions","Offsite Links","Bad Model or Script","Bad Username"}
local abuseDropDown, updateAbuseSelection = RbxGui.CreateDropDownMenu(abuses,
function(abuseText)
abuse = abuseText
if abuse and abusingPlayer then
submitReportButton.Active = true
end
end, true)
abuseDropDown.Name = "AbuseComboBox"
abuseDropDown.ZIndex = baseZIndex + 2
abuseDropDown.Position = UDim2.new(0.425, 0, 0, 142)
abuseDropDown.Size = UDim2.new(0.55,0,0,32)
abuseDropDown.Parent = settingsFrame
local shortDescriptionLabel = Instance.new("TextLabel")
shortDescriptionLabel.Name = "ShortDescriptionLabel"
shortDescriptionLabel.Text = "Short Description: (optional)"
shortDescriptionLabel.Font = Enum.Font.Arial
shortDescriptionLabel.FontSize = Enum.FontSize.Size18
shortDescriptionLabel.Position = UDim2.new(0.025,0,0,180)
shortDescriptionLabel.Size = UDim2.new(0.95,0,0,36)
shortDescriptionLabel.TextColor3 = Color3I(255,255,255)
shortDescriptionLabel.TextXAlignment = Enum.TextXAlignment.Left
shortDescriptionLabel.BackgroundTransparency = 1
shortDescriptionLabel.ZIndex = baseZIndex + 2
shortDescriptionLabel.Parent = settingsFrame
local shortDescriptionWrapper = Instance.new("Frame")
shortDescriptionWrapper.Name = "ShortDescriptionWrapper"
shortDescriptionWrapper.Position = UDim2.new(0.025,0,0,220)
shortDescriptionWrapper.Size = UDim2.new(0.95,0,1,-310)
shortDescriptionWrapper.BackgroundColor3 = Color3I(0,0,0)
shortDescriptionWrapper.BorderSizePixel = 0
shortDescriptionWrapper.ZIndex = baseZIndex + 2
shortDescriptionWrapper.Parent = settingsFrame
local shortDescriptionBox = Instance.new("TextBox")
shortDescriptionBox.Name = "TextBox"
shortDescriptionBox.Text = ""
shortDescriptionBox.ClearTextOnFocus = false
shortDescriptionBox.Font = Enum.Font.Arial
shortDescriptionBox.FontSize = Enum.FontSize.Size18
shortDescriptionBox.Position = UDim2.new(0,3,0,3)
shortDescriptionBox.Size = UDim2.new(1,-6,1,-6)
shortDescriptionBox.TextColor3 = Color3I(255,255,255)
shortDescriptionBox.TextXAlignment = Enum.TextXAlignment.Left
shortDescriptionBox.TextYAlignment = Enum.TextYAlignment.Top
shortDescriptionBox.TextWrap = true
shortDescriptionBox.BackgroundColor3 = Color3I(0,0,0)
shortDescriptionBox.BorderSizePixel = 0
shortDescriptionBox.ZIndex = baseZIndex + 2
shortDescriptionBox.Parent = shortDescriptionWrapper
submitReportButton = Instance.new("TextButton")
submitReportButton.Name = "SubmitReportBtn"
submitReportButton.Active = false
submitReportButton.Modal = true
submitReportButton.Font = Enum.Font.Arial
submitReportButton.FontSize = Enum.FontSize.Size18
submitReportButton.Position = UDim2.new(0.1, 0, 1, -80)
submitReportButton.Size = UDim2.new(0.35,0,0,50)
submitReportButton.AutoButtonColor = true
submitReportButton.Style = Enum.ButtonStyle.RobloxButtonDefault
submitReportButton.Text = "Submit Report"
submitReportButton.TextColor3 = Color3I(255,255,255)
submitReportButton.ZIndex = baseZIndex + 2
submitReportButton.Parent = settingsFrame
submitReportButton.MouseButton1Click:connect(function()
if submitReportButton.Active then
if abuse and abusingPlayer then
frame.Visible = false
game.Players:ReportAbuse(abusingPlayer, abuse, shortDescriptionBox.Text)
if abuse == "Cheating/Exploiting" then
recordedMessageBox.Visible = true
elseif abuse == "Bullying" or abuse == "Swearing" then
calmingMessageBox.Visible = true
else
normalMessageBox.Visible = true
end
else
closeAndResetDialog()
end
end
end)
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelBtn"
cancelButton.Font = Enum.Font.Arial
cancelButton.FontSize = Enum.FontSize.Size18
cancelButton.Position = UDim2.new(0.55, 0, 1, -80)
cancelButton.Size = UDim2.new(0.35,0,0,50)
cancelButton.AutoButtonColor = true
cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
cancelButton.Text = "Cancel"
cancelButton.TextColor3 = Color3I(255,255,255)
cancelButton.ZIndex = baseZIndex + 2
cancelButton.Parent = settingsFrame
closeAndResetDialog = function()
settingsButton.Active = true
currentMenuSelection = nil
lastMenuSelection = {}
--Delete old player combo box
local oldComboBox = settingsFrame:FindFirstChild("PlayersComboBox")
if oldComboBox then
oldComboBox.Parent = nil
end
abusingPlayer = nil updatePlayerSelection(nil)
abuse = nil updateAbuseSelection(nil)
submitReportButton.Active = false
shortDescriptionBox.Text = ""
frame.Visible = true
calmingMessageBox.Visible = false
recordedMessageBox.Visible = false
normalMessageBox.Visible = false
shield.Visible = false
reportAbuseButton.Active = true
game.GuiService:RemoveCenterDialog(shield)
end
cancelButton.MouseButton1Click:connect(closeAndResetDialog)
reportAbuseButton.MouseButton1Click:connect(
function()
createPlayersDropDown().Parent = settingsFrame
table.insert(centerDialogs,shield)
game.GuiService:AddCenterDialog(shield, Enum.CenterDialogType.ModalDialog,
--ShowFunction
function()
reportAbuseButton.Active = true
shield.Visible = true
mainShield.Visible = false
end,
--HideFunction
function()
reportAbuseButton.Active = true
shield.Visible = false
end)
end)
return shield
end
local createSettingsDialog = function()
waitForChild(gui,"BottomLeftControl")
settingsButton = gui.BottomLeftControl:FindFirstChild("SettingsButton")
if settingsButton == nil then
settingsButton = Instance.new("ImageButton")
settingsButton.Name = "SettingsButton"
settingsButton.Image = "rbxasset://textures/ui/SettingsButton.png"
settingsButton.BackgroundTransparency = 1
settingsButton.Active = false
settingsButton.Size = UDim2.new(0,54,0,46)
settingsButton.Position = UDim2.new(0,2,0,50)
settingsButton.Parent = gui
settingsButton.MouseButton1Click:connect(function()
goToMenu(shield.Settings.SettingsStyle,"GameMainMenu","down",UDim2.new(0,525,0,430))
shield.Settings:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
end)
end
local shield = Instance.new("TextButton")
shield.Text = ""
shield.Name = "UserSettingsShield"
shield.Active = true
shield.AutoButtonColor = false
shield.Visible = false
shield.Size = UDim2.new(1,0,1,0)
shield.BackgroundColor3 = Color3I(51,51,51)
shield.BorderColor3 = Color3I(27,42,53)
shield.BackgroundTransparency = 0.4
shield.ZIndex = baseZIndex + 2
shield.Parent = script.Parent
mainShield = shield
local frame = Instance.new("Frame")
frame.Name = "Settings"
frame.Position = UDim2.new(0.5, -262, -0.5, -200)
frame.Size = UDim2.new(0, 525, 0, 430)
frame.BackgroundTransparency = 1
frame.Active = true
frame.Parent = shield
local settingsFrame = Instance.new("Frame")
settingsFrame.Name = "SettingsStyle"
settingsFrame.Size = UDim2.new(1, 0, 1, 0)
settingsFrame.Style = Enum.FrameStyle.RobloxRound
settingsFrame.Active = true
settingsFrame.ZIndex = baseZIndex + 3
settingsFrame.Parent = frame
local gameSettingsMenu = createGameSettingsMenu(baseZIndex, shield)
gameSettingsMenu.Parent = settingsFrame
local gameReportAbuse = createReportAbuseDialog()
gameReportAbuse.Parent = script.Parent
local gameMainMenu = createGameMainMenu(baseZIndex, shield)
gameMainMenu.Parent = settingsFrame
gameMainMenu.ScreenshotButton.MouseButton1Click:connect(function()
end)
function localPlayerChange()
gameMainMenu.ResetButton.Visible = game.Players.LocalPlayer
if game.Players.LocalPlayer then
settings().Rendering.EnableFRM = true
elseif inStudioMode then
settings().Rendering.EnableFRM = false
end
end
gameMainMenu.ResetButton.Visible = game.Players.LocalPlayer
if game.Players.LocalPlayer ~= nil then
game.Players.LocalPlayer.Changed:connect(function()
localPlayerChange()
end)
else
delay(0,function()
waitForProperty(game.Players,"LocalPlayer")
gameMainMenu.ResetButton.Visible = game.Players.LocalPlayer
game.Players.LocalPlayer.Changed:connect(function()
localPlayerChange()
end)
end)
end
gameMainMenu.ReportAbuseButton.Visible = game:FindFirstChild("NetworkClient")
if not gameMainMenu.ReportAbuseButton.Visible then
game.ChildAdded:connect(function(child)
if child:IsA("NetworkClient") then
gameMainMenu.ReportAbuseButton.Visible = game:FindFirstChild("NetworkClient")
end
end)
end
gameMainMenu.ResetButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"ResetConfirmationMenu","up",UDim2.new(0,525,0,370))
end)
gameMainMenu.LeaveGameButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"LeaveConfirmationMenu","down",UDim2.new(0,525,0,300))
end)
local gameSettingsMenu = createGameSettingsMenu(baseZIndex, shield)
gameSettingsMenu.Visible = false
gameSettingsMenu.Parent = settingsFrame
gameMainMenu.LeaveGameButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"LeaveConfirmationMenu","down",UDim2.new(0,525,0,300))
end)
gameMainMenu.SettingsButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"GameSettingsMenu","left",UDim2.new(0,525,0,350))
end)
gameSettingsMenu.BackButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430))
end)
local resetConfirmationWindow = createResetConfirmationMenu(baseZIndex, shield)
resetConfirmationWindow.Visible = false
resetConfirmationWindow.Parent = settingsFrame
local leaveConfirmationWindow = createLeaveConfirmationMenu(baseZIndex,shield)
leaveConfirmationWindow.Visible = false
leaveConfirmationWindow.Parent = settingsFrame
settingsButton.MouseButton1Click:connect(
function()
game.GuiService:AddCenterDialog(shield, Enum.CenterDialogType.ModalDialog,
--showFunction
function()
settingsButton.Active = false
updateCameraDropDownSelection(UserSettings().GameSettings.ControlMode.Name)
if syncVideoCaptureSetting then
syncVideoCaptureSetting()
end
goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430))
shield.Visible = true
settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
end,
--hideFunction
function()
settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,-0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
shield.Visible = false
settingsButton.Active = true
end)
end)
return shield
end
delay(0, function()
if settingsButton == nil then
settingsButton = Instance.new("ImageButton")
settingsButton.Name = "SettingsButton"
settingsButton.Image = "rbxasset://textures/ui/SettingsButton.png"
settingsButton.BackgroundTransparency = 1
settingsButton.Active = false
settingsButton.Size = UDim2.new(0,54,0,46)
settingsButton.Position = UDim2.new(0,2,0,50)
settingsButton.Parent = gui.BottomLeftControl
end
local shield = Instance.new("TextButton")
shield.Text = ""
shield.Name = "UserSettingsShield"
shield.Active = true
shield.AutoButtonColor = false
shield.Visible = false
shield.Size = UDim2.new(1,0,1,0)
shield.BackgroundColor3 = Color3I(51,51,51)
shield.BorderColor3 = Color3I(27,42,53)
shield.BackgroundTransparency = 0.4
shield.ZIndex = baseZIndex + 2
shield.Parent = script.Parent
mainShield = shield
local frame = Instance.new("Frame")
frame.Name = "Settings"
frame.Position = UDim2.new(0.5, -262, -0.5, -200)
frame.Size = UDim2.new(0, 525, 0, 430)
frame.BackgroundTransparency = 1
frame.Active = true
frame.Parent = shield
local settingsFrame = Instance.new("Frame")
settingsFrame.Name = "SettingsStyle"
settingsFrame.Size = UDim2.new(1, 0, 1, 0)
settingsFrame.Style = Enum.FrameStyle.RobloxRound
settingsFrame.Active = true
settingsFrame.ZIndex = baseZIndex + 3
settingsFrame.Parent = frame
local resetConfirmationWindow = createResetConfirmationMenu(baseZIndex, shield)
resetConfirmationWindow.Visible = false
resetConfirmationWindow.Parent = settingsFrame
local leaveConfirmationWindow = createLeaveConfirmationMenu(baseZIndex,shield)
leaveConfirmationWindow.Visible = false
leaveConfirmationWindow.Parent = settingsFrame
local gameMainMenu = createGameMainMenu(baseZIndex, shield)
gameMainMenu.Parent = settingsFrame
local gameSettingsMenu = createGameSettingsMenu(baseZIndex, shield)
gameSettingsMenu.Visible = false
gameSettingsMenu.Parent = settingsFrame
gameMainMenu.SettingsButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"GameSettingsMenu","left",UDim2.new(0,525,0,350))
end)
gameSettingsMenu.BackButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430))
end)
gameMainMenu.ResetButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"ResetConfirmationMenu","up",UDim2.new(0,525,0,370))
end)
gameMainMenu.LeaveGameButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"LeaveConfirmationMenu","up",UDim2.new(0,525,0,300))
end)
gameMainMenu.ScreenshotButton.MouseButton1Click:connect(function()
end)
settingsButton.MouseButton1Click:connect(function()
goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430))
shield.Visible = true
shield.Active = true
settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
end)
game:GetService("GuiService").EscapeKeyPressed:connect(function()
if shield.Visible == false then
goToMenu(settingsFrame,"GameMainMenu","right",UDim2.new(0,525,0,430))
shield.Visible = true
shield.Active = true
settingsFrame.Parent:TweenPosition(UDim2.new(0.5, -262,0.5, -200),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
settingsFrame.Parent:TweenSize(UDim2.new(0,525,0,430),Enum.EasingDirection.InOut,Enum.EasingStyle.Sine,tweenTime,true)
elseif shield.Visible == true then
resumeGameFunction(shield)
end
end)
gui.BottomLeftControl.SettingsButton.Active = true
gui.BottomLeftControl.SettingsButton.Position = UDim2.new(0,2,0,-2)
if mouseLockLabel and UserSettings().GameSettings.ControlMode == Enum.ControlMode["Mouse Lock Switch"] then
mouseLockLabel.Visible = true
elseif mouseLockLabel then
mouseLockLabel.Visible = false
end
local createSaveDialogs = function()
local shield = Instance.new("TextButton")
shield.Text = ""
shield.AutoButtonColor = false
shield.Name = "SaveDialogShield"
shield.Active = true
shield.Visible = false
shield.Size = UDim2.new(1,0,1,0)
shield.BackgroundColor3 = Color3I(51,51,51)
shield.BorderColor3 = Color3I(27,42,53)
shield.BackgroundTransparency = 0.4
shield.ZIndex = baseZIndex+1
local clearAndResetDialog
local save
local saveLocal
local dontSave
local cancel
local messageBoxButtons = {}
messageBoxButtons[1] = {}
messageBoxButtons[1].Text = "Save"
messageBoxButtons[1].Style = Enum.ButtonStyle.RobloxButtonDefault
messageBoxButtons[1].Function = function() save() end
messageBoxButtons[2] = {}
messageBoxButtons[2].Text = "Cancel"
messageBoxButtons[2].Function = function() cancel() end
messageBoxButtons[3] = {}
messageBoxButtons[3].Text = "Don't Save"
messageBoxButtons[3].Function = function() dontSave() end
local saveDialogMessageBox = RbxGui.CreateStyledMessageDialog("Unsaved Changes", "Save your changes to ROBLOX before leaving?", "Confirm", messageBoxButtons)
saveDialogMessageBox.Visible = true
saveDialogMessageBox.Parent = shield
local errorBoxButtons = {}
local buttonOffset = 1
if game.LocalSaveEnabled then
errorBoxButtons[buttonOffset] = {}
errorBoxButtons[buttonOffset].Text = "Save to Disk"
errorBoxButtons[buttonOffset].Function = function() saveLocal() end
buttonOffset = buttonOffset + 1
end
errorBoxButtons[buttonOffset] = {}
errorBoxButtons[buttonOffset].Text = "Keep Playing"
errorBoxButtons[buttonOffset].Function = function() cancel() end
errorBoxButtons[buttonOffset+1] = {}
errorBoxButtons[buttonOffset+1].Text = "Don't Save"
errorBoxButtons[buttonOffset+1].Function = function() dontSave() end
local errorDialogMessageBox = RbxGui.CreateStyledMessageDialog("Upload Failed", "Sorry, we could not save your changes to ROBLOX.", "Error", errorBoxButtons)
errorDialogMessageBox.Visible = false
errorDialogMessageBox.Parent = shield
local spinnerDialog = Instance.new("Frame")
spinnerDialog.Name = "SpinnerDialog"
spinnerDialog.Style = Enum.FrameStyle.RobloxRound
spinnerDialog.Size = UDim2.new(0, 350, 0, 150)
spinnerDialog.Position = UDim2.new(.5, -175, .5, -75)
spinnerDialog.Visible = false
spinnerDialog.Active = true
spinnerDialog.Parent = shield
local waitingLabel = Instance.new("TextLabel")
waitingLabel.Name = "WaitingLabel"
waitingLabel.Text = "Saving to ROBLOX..."
waitingLabel.Font = Enum.Font.ArialBold
waitingLabel.FontSize = Enum.FontSize.Size18
waitingLabel.Position = UDim2.new(0.5, 25, 0.5, 0)
waitingLabel.TextColor3 = Color3.new(1,1,1)
waitingLabel.Parent = spinnerDialog
local spinnerFrame = Instance.new("Frame")
spinnerFrame.Name = "Spinner"
spinnerFrame.Size = UDim2.new(0, 80, 0, 80)
spinnerFrame.Position = UDim2.new(0.5, -150, 0.5, -40)
spinnerFrame.BackgroundTransparency = 1
spinnerFrame.Parent = spinnerDialog
local spinnerIcons = {}
local spinnerNum = 1
while spinnerNum <= 8 do
local spinnerImage = Instance.new("ImageLabel")
spinnerImage.Name = "Spinner"..spinnerNum
spinnerImage.Size = UDim2.new(0, 16, 0, 16)
spinnerImage.Position = UDim2.new(.5+.3*math.cos(math.rad(45*spinnerNum)), -8, .5+.3*math.sin(math.rad(45*spinnerNum)), -8)
spinnerImage.BackgroundTransparency = 1
spinnerImage.Image = "http://www.roblox.com/Asset?id=45880710"
spinnerImage.Parent = spinnerFrame
spinnerIcons[spinnerNum] = spinnerImage
spinnerNum = spinnerNum + 1
end
save = function()
saveDialogMessageBox.Visible = false
--Show the spinner dialog
spinnerDialog.Visible = true
local spin = true
--Make it spin
delay(0, function()
local spinPos = 0
while spin do
local pos = 0
while pos < 8 do
if pos == spinPos or pos == ((spinPos+1)%8) then
spinnerIcons[pos+1].Image = "http://www.roblox.com/Asset?id=45880668"
else
spinnerIcons[pos+1].Image = "http://www.roblox.com/Asset?id=45880710"
end
pos = pos + 1
end
spinPos = (spinPos + 1) % 8
wait(0.2)
end
end)
--Do the save while the spinner is going, function will wait
local result = game:SaveToRoblox()
if not result then
--Try once more
result = game:SaveToRoblox()
end
--Hide the spinner dialog
spinnerDialog.Visible = false
--And cause the delay thread to stop
spin = false
--Now process the result
if result then
--Success, close
game:FinishShutdown(false)
clearAndResetDialog()
else
--Failure, show the second dialog prompt
errorDialogMessageBox.Visible = true
end
end
saveLocal = function()
errorDialogMessageBox.Visible = false
game:FinishShutdown(true)
clearAndResetDialog()
end
dontSave = function()
saveDialogMessageBox.Visible = false
errorDialogMessageBox.Visible = false
game:FinishShutdown(false)
clearAndResetDialog()
end
cancel = function()
saveDialogMessageBox.Visible = false
errorDialogMessageBox.Visible = false
clearAndResetDialog()
end
clearAndResetDialog = function()
saveDialogMessageBox.Visible = true
errorDialogMessageBox.Visible = false
spinnerDialog.Visible = false
shield.Visible = false
game.GuiService:RemoveCenterDialog(shield)
end
shield.Visible = false
return shield
end
local createChatBar = function()
--Only show a chat bar if we are a NetworkClient
waitForChild(game, "NetworkClient")
waitForChild(game, "Players")
waitForProperty(game.Players, "LocalPlayer")
local chatBar = Instance.new("Frame")
chatBar.Name = "ChatBar"
chatBar.Size = UDim2.new(1, 0, 0, 22)
chatBar.Position = UDim2.new(0, 0, 1, 0)
chatBar.BackgroundColor3 = Color3.new(0,0,0)
chatBar.BorderSizePixel = 0
local chatBox = Instance.new("TextBox")
chatBox.Text = ""
chatBox.Visible = false
chatBox.Size = UDim2.new(1,-4,1,0)
chatBox.Position = UDim2.new(0,2,0,0)
chatBox.TextXAlignment = Enum.TextXAlignment.Left
chatBox.Font = Enum.Font.Arial
chatBox.ClearTextOnFocus = false
chatBox.FontSize = Enum.FontSize.Size14
chatBox.TextColor3 = Color3.new(1,1,1)
chatBox.BackgroundTransparency = 1
--chatBox.Parent = chatBar
local chatButton = Instance.new("TextButton")
chatButton.Size = UDim2.new(1,-4,1,0)
chatButton.Position = UDim2.new(0,2,0,0)
chatButton.AutoButtonColor = false
chatButton.Text = "To chat click here or press \"/\" key"
chatButton.TextXAlignment = Enum.TextXAlignment.Left
chatButton.Font = Enum.Font.Arial
chatButton.FontSize = Enum.FontSize.Size14
chatButton.TextColor3 = Color3.new(1,1,1)
chatButton.BackgroundTransparency = 1
--chatButton.Parent = chatBar
local activateChat = function()
if chatBox.Visible then
return
end
chatButton.Visible = false
chatBox.Text = ""
chatBox.Visible = true
chatBox:CaptureFocus()
end
chatButton.MouseButton1Click:connect(activateChat)
local hotKeyEnabled = true
local toggleHotKey = function(value)
hotKeyEnabled = value
end
local guiService = game:GetService("GuiService")
local newChatMode = pcall(function()
--guiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey)
--guiService.SpecialKeyPressed:connect(function(key) if key == Enum.SpecialKey.ChatHotkey and hotKeyEnabled then activateChat() end end)
end)
if not newChatMode then
--guiService:AddKey("/")
--guiService.KeyPressed:connect(function(key) if key == "/" and hotKeyEnabled then activateChat() end end)
end
chatBox.FocusLost:connect(
function(enterPressed)
if enterPressed then
if chatBox.Text ~= "" then
local str = chatBox.Text
if string.sub(str, 1, 1) == '%' then
game.Players:TeamChat(string.sub(str, 2))
else
game.Players:Chat(str)
end
end
end
chatBox.Text = ""
chatBox.Visible = false
chatButton.Visible = true
end)
return chatBar, toggleHotKey
end
--Spawn a thread for the Save dialogs
local isSaveDialogSupported = pcall(function() local var = game.LocalSaveEnabled end)
if isSaveDialogSupported then
delay(0,
function()
local saveDialogs = createSaveDialogs()
saveDialogs.Parent = gui
game.RequestShutdown = function()
table.insert(centerDialogs,saveDialogs)
game.GuiService:AddCenterDialog(saveDialogs, Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
saveDialogs.Visible = true
end,
--HideFunction
function()
saveDialogs.Visible = false
end)
return true
end
end)
end
end)
--Spawn a thread for the Report Abuse dialogs
delay(0,
function()
createReportAbuseDialog().Parent = script.Parent
waitForChild(gui,"UserSettingsShield")
waitForChild(gui.UserSettingsShield, "Settings")
waitForChild(gui.UserSettingsShield.Settings,"SettingsStyle")
waitForChild(gui.UserSettingsShield.Settings.SettingsStyle,"GameMainMenu")
waitForChild(gui.UserSettingsShield.Settings.SettingsStyle.GameMainMenu, "ReportAbuseButton")
gui.UserSettingsShield.Settings.SettingsStyle.GameMainMenu.ReportAbuseButton.Active = true
end)
end --LoadLibrary if
end
-
Notifications
-
false
Init
--rbxsig%DIuke4NUwBAugRhVX8zUGw0lNHksGNmUbxnUjItyfN6YfmsPF6w9OML1jkc9uaOFfrayWCJEroukxRmuvY9E5jVqOM8TBXgRXfyVoJsVQ+YRTUdE1U1Jn/X7+oh/W1LN8Ayn42HhTEVjEbpVV+BHAeQZpjZltXo5qyozomUTeQE=%
--rbxassetid%48488398%
function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForProperty(game.Players,"LocalPlayer")
waitForChild(script.Parent,"Popup")
waitForChild(script.Parent.Popup,"AcceptButton")
script.Parent.Popup.AcceptButton.Modal = true
local localPlayer = game.Players.LocalPlayer
local acceptedTeleport = Instance.new("IntValue")
local friendRequestBlacklist = {}
local teleportEnabled = true
local makePopupInvisible = function()
if script.Parent.Popup then script.Parent.Popup.Visible = false end
end
function makeFriend(fromPlayer,toPlayer)
local popup = script.Parent:FindFirstChild("Popup")
if popup == nil then return end -- there is no popup!
if popup.Visible then return end -- currently popping something, abort!
if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it!
popup.PopupText.Text = "Accept Friend Request from " .. tostring(fromPlayer.Name) .. "?"
popup.PopupImage.Image = "http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=352&y=352"
showTwoButtons()
popup.Visible = true
popup.AcceptButton.Text = "Accept"
popup.DeclineButton.Text = "Decline"
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
local yesCon, noCon
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
popup.Visible = false
toPlayer:RequestFriendship(fromPlayer)
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
popup.Visible = false
toPlayer:RevokeFriendship(fromPlayer)
friendRequestBlacklist[fromPlayer] = true
print("pop up blacklist")
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
game.Players.FriendRequestEvent:connect(function(fromPlayer,toPlayer,event)
-- if this doesn't involve me, then do nothing
if fromPlayer ~= localPlayer and toPlayer ~= localPlayer then return end
if fromPlayer == localPlayer then
if event == Enum.FriendRequestEvent.Accept then
game:GetService("GuiService"):SendNotification("You are Friends",
"With " .. toPlayer.Name .. "!",
"http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(toPlayer.userId).."&x=48&y=48",
5,
function()
end)
end
elseif toPlayer == localPlayer then
if event == Enum.FriendRequestEvent.Issue then
if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it!
game:GetService("GuiService"):SendNotification("Friend Request",
"From " .. fromPlayer.Name,
"http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=48&y=48",
8,
function()
makeFriend(fromPlayer,toPlayer)
end)
elseif event == Enum.FriendRequestEvent.Accept then
game:GetService("GuiService"):SendNotification("You are Friends",
"With " .. fromPlayer.Name .. "!",
"http://www.roblox.com/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=48&y=48",
5,
function()
end)
end
end
end)
function showOneButton()
local popup = script.Parent:FindFirstChild("Popup")
if popup then
popup.OKButton.Visible = true
popup.DeclineButton.Visible = false
popup.AcceptButton.Visible = false
end
end
function showTwoButtons()
local popup = script.Parent:FindFirstChild("Popup")
if popup then
popup.DeclineButton.Visible = true
popup.AcceptButton.Visible = true
end
end
if teleportEnabled then
game:GetService("TeleportService").ErrorCallback = function(message)
local popup = script.Parent:FindFirstChild("Popup")
showOneButton()
popup.PopupText.Text = message
local clickCon
clickCon = popup.OKButton.MouseButton1Click:connect(function()
if clickCon then clickCon:disconnect() end
game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showOneButton()
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
game:GetService("TeleportService").ConfirmationCallback = function(message, placeId, spawnName)
local popup = script.Parent:FindFirstChild("Popup")
popup.PopupText.Text = message
popup.PopupImage.Image = ""
local yesCon, noCon
local function killCons()
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
killCons()
local success, err = pcall(function() game:GetService("TeleportService"):TeleportImpl(placeId,spawnName) end)
if not success then
showOneButton()
popup.PopupText.Text = err
local clickCon
clickCon = popup.OKButton.MouseButton1Click:connect(function()
if clickCon then clickCon:disconnect() end
game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showOneButton()
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
killCons()
local success = pcall(function() game:GetService("TeleportService"):TeleportCancel() end)
end)
local centerDialogSuccess = pcall(function() game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showTwoButtons()
popup.AcceptButton.Text = "Leave"
popup.DeclineButton.Text = "Stay"
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end)
if centerDialogSuccess == false then
script.Parent:FindFirstChild("Popup").Visible = true
popup.AcceptButton.Text = "Leave"
popup.DeclineButton.Text = "Stay"
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end
return true
end
end
-
false
PopupScript
--rbxsig%kFJjpVHvWkJX02PNT/54It5wEJZscSSdzAhjsXr0WtGNy+idQIKiWTiMUqEANPv/ST8P3B5jNDPtM9SNqR53nY9P6B1PAS08ik0AquNdrWORpnFHwksP3xC2ysi2Y1LsByVO2Uj0FikBhLe1CAVmlmX22AqbO/qNaL26sftSHT0=%
--rbxassetid%48488451%
--build our gui
local popupFrame = Instance.new("Frame")
popupFrame.Position = UDim2.new(0.5,-165,0.5,-175)
popupFrame.Size = UDim2.new(0,330,0,350)
popupFrame.Style = Enum.FrameStyle.RobloxRound
popupFrame.ZIndex = 4
popupFrame.Name = "Popup"
popupFrame.Visible = false
popupFrame.Parent = script.Parent
local darken = popupFrame:clone()
darken.Size = UDim2.new(1,16,1,16)
darken.Position = UDim2.new(0,-8,0,-8)
darken.Name = "Darken"
darken.ZIndex = 1
darken.Parent = popupFrame
local acceptButton = Instance.new("TextButton")
acceptButton.Position = UDim2.new(0,20,0,270)
acceptButton.Size = UDim2.new(0,100,0,50)
acceptButton.Font = Enum.Font.ArialBold
acceptButton.FontSize = Enum.FontSize.Size24
acceptButton.Style = Enum.ButtonStyle.RobloxButton
acceptButton.TextColor3 = Color3.new(248/255,248/255,248/255)
acceptButton.Text = "Yes"
acceptButton.ZIndex = 5
acceptButton.Name = "AcceptButton"
acceptButton.Parent = popupFrame
local declineButton = acceptButton:clone()
declineButton.Position = UDim2.new(1,-120,0,270)
declineButton.Text = "No"
declineButton.Name = "DeclineButton"
declineButton.Parent = popupFrame
local popupImage = Instance.new("ImageLabel")
popupImage.BackgroundTransparency = 1
popupImage.Position = UDim2.new(0.5,-140,0,0)
popupImage.Size = UDim2.new(0,280,0,280)
popupImage.ZIndex = 3
popupImage.Name = "PopupImage"
popupImage.Parent = popupFrame
local backing = Instance.new("ImageLabel")
backing.BackgroundTransparency = 1
backing.Size = UDim2.new(1,0,1,0)
backing.Image = "http://www.roblox.com/asset/?id=47574181"
backing.Name = "Backing"
backing.ZIndex = 2
backing.Parent = popupImage
local popupText = Instance.new("TextLabel")
popupText.Name = "PopupText"
popupText.Size = UDim2.new(1,0,0.8,0)
popupText.Font = Enum.Font.ArialBold
popupText.FontSize = Enum.FontSize.Size36
popupText.BackgroundTransparency = 1
popupText.Text = "Hello I'm a popup"
popupText.TextColor3 = Color3.new(248/255,248/255,248/255)
popupText.TextWrap = true
popupText.ZIndex = 5
popupText.Parent = popupFrame
script:remove()
-
Playerlist
-
false
Init
-- welcome to second version of playerlist!!! --
-- change log:
-- 1 using a later version of playerlist which means more stability!!!!1 --
-- 2 stat names now work!!! --
-- made by iago#6808 --
local t = {}
local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
local eventConnection = nil
--Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
local tryConnect = function()
if game:IsAncestorOf(parentInstance) then
--Entering the world, make sure we are connected/synced
if not eventConnection then
eventConnection = instance[event]:connect(signalFunc)
if syncFunc then syncFunc() end
end
else
--Probably leaving the world, so disconnect for now
if eventConnection then
eventConnection:disconnect()
if removeFunc then removeFunc() end
end
end
end
--Hook it up to ancestryChanged signal
local connection = parentInstance.AncestryChanged:connect(tryConnect)
--Now connect us if we're already in the world
tryConnect()
return connection
end
local function getScreenGuiAncestor(instance)
local localInstance = instance
while localInstance and not localInstance:IsA("ScreenGui") do
localInstance = localInstance.Parent
end
return localInstance
end
local function CreateButtons(frame, buttons, yPos, ySize)
local buttonNum = 1
local buttonObjs = {}
for i, obj in ipairs(buttons) do
local button = Instance.new("TextButton")
button.Name = "Button" .. buttonNum
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size18
button.AutoButtonColor = true
button.Modal = true
if obj["Style"] then
button.Style = obj.Style
else
button.Style = Enum.ButtonStyle.RobloxButton
end
if obj["ZIndex"] then
button.ZIndex = obj.ZIndex
end
button.Text = obj.Text
button.TextColor3 = Color3.new(1,1,1)
button.MouseButton1Click:connect(obj.Function)
button.Parent = frame
buttonObjs[buttonNum] = button
buttonNum = buttonNum + 1
end
local numButtons = buttonNum-1
if numButtons == 1 then
frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
elseif numButtons == 2 then
frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
elseif numButtons >= 3 then
local spacing = .1 / numButtons
local buttonSize = .9 / numButtons
buttonNum = 1
while buttonNum <= numButtons do
buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
buttonNum = buttonNum + 1
end
end
end
local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
local newStep = steps - 1 --otherwise we really get one more step than we want
local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
local wholeNum, remainder = math.modf(relativePosX * newStep)
if remainder > 0.5 then
wholeNum = wholeNum + 1
end
relativePosX = wholeNum/newStep
local result = math.ceil(relativePosX * newStep)
if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
sliderPosition.Value = result + 1
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end
end
local function cancelSlide(areaSoak)
areaSoak.Visible = false
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
end
t.CreateStyledMessageDialog = function(title, message, style, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0, 165)
frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local styleImage = Instance.new("ImageLabel")
styleImage.Name = "StyleImage"
styleImage.BackgroundTransparency = 1
styleImage.Position = UDim2.new(0,5,0,15)
if style == "error" or style == "Error" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42565285"
elseif style == "notify" or style == "Notify" then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = "http://www.roblox.com/asset/?id=42604978"
elseif style == "confirm" or style == "Confirm" then
styleImage.Size = UDim2.new(0, 74, 0, 76)
styleImage.Image = "http://www.roblox.com/asset/?id=42557901"
else
return t.CreateMessageDialog(title,message,buttons)
end
styleImage.Parent = frame
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.TextStrokeTransparency = 0
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 80, 0, 0)
titleLabel.Size = UDim2.new(1, -80, 0, 40)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextStrokeTransparency = 0
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
return frame
end
t.CreateMessageDialog = function(title, message, buttons)
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0.5, 0, 0.5, 0)
frame.Position = UDim2.new(0.25, 0, 0.25, 0)
frame.Name = "MessageDialog"
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local titleLabel = Instance.new("TextLabel")
titleLabel.Name = "Title"
titleLabel.Text = title
titleLabel.BackgroundTransparency = 1
titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
titleLabel.Position = UDim2.new(0, 0, 0, 0)
titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
titleLabel.Font = Enum.Font.ArialBold
titleLabel.FontSize = Enum.FontSize.Size36
titleLabel.TextXAlignment = Enum.TextXAlignment.Center
titleLabel.TextYAlignment = Enum.TextYAlignment.Center
titleLabel.Parent = frame
local messageLabel = Instance.new("TextLabel")
messageLabel.Name = "Message"
messageLabel.Text = message
messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
messageLabel.BackgroundTransparency = 1
messageLabel.Font = Enum.Font.Arial
messageLabel.FontSize = Enum.FontSize.Size18
messageLabel.TextWrap = true
messageLabel.TextXAlignment = Enum.TextXAlignment.Left
messageLabel.TextYAlignment = Enum.TextYAlignment.Top
messageLabel.Parent = frame
CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
return frame
end
t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ)
local baseZIndex = 0
if (type(baseZ) == "number") then
baseZIndex = baseZ
end
local width = UDim.new(0, 100)
local height = UDim.new(0, 32)
local xPos = 0.055
local frame = Instance.new("Frame")
local textColor = Color3.new(1,1,1)
if (whiteSkin) then
textColor = Color3.new(0.5, 0.5, 0.5)
end
frame.Name = "DropDownMenu"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(width, height)
local dropDownMenu = Instance.new("TextButton")
dropDownMenu.Name = "DropDownMenuButton"
dropDownMenu.TextWrap = true
dropDownMenu.TextColor3 = textColor
dropDownMenu.Text = "Choose One"
dropDownMenu.Font = Enum.Font.ArialBold
dropDownMenu.FontSize = Enum.FontSize.Size18
dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
dropDownMenu.BackgroundTransparency = 1
dropDownMenu.AutoButtonColor = true
if (whiteSkin) then
dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
dropDownMenu.Size = UDim2.new(1,0,1,0)
dropDownMenu.Parent = frame
dropDownMenu.ZIndex = 2 + baseZIndex
local dropDownIcon = Instance.new("ImageLabel")
dropDownIcon.Name = "Icon"
dropDownIcon.Active = false
if (whiteSkin) then
dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png"
dropDownIcon.Size = UDim2.new(0,16,0,12)
dropDownIcon.Position = UDim2.new(1,-17,0.5, -6)
else
dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894"
dropDownIcon.Size = UDim2.new(0,11,0,6)
dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
end
dropDownIcon.BackgroundTransparency = 1
dropDownIcon.Parent = dropDownMenu
dropDownIcon.ZIndex = 2 + baseZIndex
local itemCount = #items
local dropDownItemCount = #items
local useScrollButtons = false
if dropDownItemCount > 6 then
useScrollButtons = true
dropDownItemCount = 6
end
local droppedDownMenu = Instance.new("TextButton")
droppedDownMenu.Name = "List"
droppedDownMenu.Text = ""
droppedDownMenu.BackgroundTransparency = 1
--droppedDownMenu.AutoButtonColor = true
if (whiteSkin) then
droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
else
droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
end
droppedDownMenu.Visible = false
droppedDownMenu.Active = true --Blocks clicks
droppedDownMenu.Position = UDim2.new(0,0,0,0)
droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
droppedDownMenu.Parent = frame
droppedDownMenu.ZIndex = 2 + baseZIndex
local choiceButton = Instance.new("TextButton")
choiceButton.Name = "ChoiceButton"
choiceButton.BackgroundTransparency = 1
choiceButton.BorderSizePixel = 0
choiceButton.Text = "ReplaceMe"
choiceButton.TextColor3 = textColor
choiceButton.TextXAlignment = Enum.TextXAlignment.Left
choiceButton.TextYAlignment = Enum.TextYAlignment.Center
choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
choiceButton.Font = Enum.Font.Arial
choiceButton.FontSize = Enum.FontSize.Size18
if useScrollButtons then
choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
else
choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
end
choiceButton.TextWrap = true
choiceButton.ZIndex = 2 + baseZIndex
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = true
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 3 + baseZIndex
local dropDownSelected = false
local scrollUpButton
local scrollDownButton
local scrollMouseCount = 0
local setZIndex = function(baseZIndex)
droppedDownMenu.ZIndex = baseZIndex +1
if scrollUpButton then
scrollUpButton.ZIndex = baseZIndex + 3
end
if scrollDownButton then
scrollDownButton.ZIndex = baseZIndex + 3
end
local children = droppedDownMenu:GetChildren()
if children then
for i, child in ipairs(children) do
if child.Name == "ChoiceButton" then
child.ZIndex = baseZIndex + 2
elseif child.Name == "ClickCaptureButton" then
child.ZIndex = baseZIndex
end
end
end
end
local scrollBarPosition = 1
local updateScroll = function()
if scrollUpButton then
scrollUpButton.Active = scrollBarPosition > 1
end
if scrollDownButton then
scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
end
local children = droppedDownMenu:GetChildren()
if not children then return end
local childNum = 1
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
obj.Visible = false
else
obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
obj.Visible = true
end
obj.TextColor3 = textColor
obj.BackgroundTransparency = 1
childNum = childNum + 1
end
end
end
local toggleVisibility = function()
dropDownSelected = not dropDownSelected
areaSoak.Visible = not areaSoak.Visible
dropDownMenu.Visible = not dropDownSelected
droppedDownMenu.Visible = dropDownSelected
if dropDownSelected then
setZIndex(4 + baseZIndex)
else
setZIndex(2 + baseZIndex)
end
if useScrollButtons then
updateScroll()
end
end
droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
local updateSelection = function(text)
local foundItem = false
local children = droppedDownMenu:GetChildren()
local childNum = 1
if children then
for i, obj in ipairs(children) do
if obj.Name == "ChoiceButton" then
if obj.Text == text then
obj.Font = Enum.Font.ArialBold
foundItem = true
scrollBarPosition = childNum
if (whiteSkin) then
obj.TextColor3 = Color3.new(90/255,142/255,233/255)
end
else
obj.Font = Enum.Font.Arial
if (whiteSkin) then
obj.TextColor3 = textColor
end
end
childNum = childNum + 1
end
end
end
if not text then
dropDownMenu.Text = "Choose One"
scrollBarPosition = 1
else
if not foundItem then
error("Invalid Selection Update -- " .. text)
end
if scrollBarPosition + dropDownItemCount > itemCount + 1 then
scrollBarPosition = itemCount - dropDownItemCount + 1
end
dropDownMenu.Text = text
end
end
local function scrollDown()
if scrollBarPosition + dropDownItemCount <= itemCount then
scrollBarPosition = scrollBarPosition + 1
updateScroll()
return true
end
return false
end
local function scrollUp()
if scrollBarPosition > 1 then
scrollBarPosition = scrollBarPosition - 1
updateScroll()
return true
end
return false
end
if useScrollButtons then
--Make some scroll buttons
scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
scrollUpButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollUp()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollUp() == false then
break
end
wait(0.1)
end
end)
scrollUpButton.Parent = droppedDownMenu
scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
scrollDownButton.Position = UDim2.new(1,-11,1,-11)
scrollDownButton.Parent = droppedDownMenu
scrollDownButton.MouseButton1Click:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseLeave:connect(
function()
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollMouseCount = scrollMouseCount + 1
scrollDown()
local val = scrollMouseCount
wait(0.5)
while val == scrollMouseCount do
if scrollDown() == false then
break
end
wait(0.1)
end
end)
local scrollbar = Instance.new("ImageLabel")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
scrollbar.Parent = droppedDownMenu
end
for i,item in ipairs(items) do
-- needed to maintain local scope for items in event listeners below
local button = choiceButton:clone()
button.Text = item
button.Parent = droppedDownMenu
if (whiteSkin) then
button.TextColor3 = textColor
end
button.MouseButton1Click:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
updateSelection(item)
onSelect(item)
toggleVisibility()
end)
button.MouseEnter:connect(function()
--Add Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(0,0,0)
end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function()
--Remove Highlight
if (not whiteSkin) then
button.TextColor3 = Color3.new(1,1,1)
end
button.BackgroundTransparency = 1
end)
end
--This does the initial layout of the buttons
updateScroll()
frame.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(frame)
end
end)
dropDownMenu.MouseButton1Click:connect(toggleVisibility)
areaSoak.MouseButton1Click:connect(toggleVisibility)
return frame, updateSelection
end
t.CreatePropertyDropDownMenu = function(instance, property, enum)
local items = enum:GetEnumItems()
local names = {}
local nameToItem = {}
for i,obj in ipairs(items) do
names[i] = obj.Name
nameToItem[obj.Name] = obj
end
local frame
local updateSelection
frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
ScopedConnect(frame, instance, "Changed",
function(prop)
if prop == property then
updateSelection(instance[property].Name)
end
end,
function()
updateSelection(instance[property].Name)
end)
return frame
end
t.GetFontHeight = function(font, fontSize)
if font == nil or fontSize == nil then
error("Font and FontSize must be non-nil")
end
if font == Enum.Font.Legacy then
if fontSize == Enum.FontSize.Size8 then
return 12
elseif fontSize == Enum.FontSize.Size9 then
return 14
elseif fontSize == Enum.FontSize.Size10 then
return 15
elseif fontSize == Enum.FontSize.Size11 then
return 17
elseif fontSize == Enum.FontSize.Size12 then
return 18
elseif fontSize == Enum.FontSize.Size14 then
return 21
elseif fontSize == Enum.FontSize.Size18 then
return 27
elseif fontSize == Enum.FontSize.Size24 then
return 36
elseif fontSize == Enum.FontSize.Size36 then
return 54
elseif fontSize == Enum.FontSize.Size48 then
return 72
else
error("Unknown FontSize")
end
elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
if fontSize == Enum.FontSize.Size8 then
return 8
elseif fontSize == Enum.FontSize.Size9 then
return 9
elseif fontSize == Enum.FontSize.Size10 then
return 10
elseif fontSize == Enum.FontSize.Size11 then
return 11
elseif fontSize == Enum.FontSize.Size12 then
return 12
elseif fontSize == Enum.FontSize.Size14 then
return 14
elseif fontSize == Enum.FontSize.Size18 then
return 18
elseif fontSize == Enum.FontSize.Size24 then
return 24
elseif fontSize == Enum.FontSize.Size36 then
return 36
elseif fontSize == Enum.FontSize.Size48 then
return 48
else
error("Unknown FontSize")
end
else
error("Unknown Font " .. font)
end
end
local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
for i, child in ipairs(guiObjects) do
if child:IsA("TextLabel") or child:IsA("TextButton") then
local isLabel = child:IsA("TextLabel")
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
if child.TextFits and child.TextBounds.Y < pixelsRemaining then
child.Visible = true
if isLabel then
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
else
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
end
while not child.TextFits do
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
end
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
else
pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
end
else
child.Visible = false
pixelsRemaining = -1
end
else
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
child.Visible = (pixelsRemaining >= 0)
end
end
end
t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
if not frame:IsA("GuiObject") then
error("Frame must be a GuiObject")
end
for i, child in ipairs(guiObjects) do
if not child:IsA("GuiObject") then
error("All elements that are layed out must be of type GuiObject")
end
end
if not settingsTable then
settingsTable = {}
end
if not settingsTable["TextLabelSizePadY"] then
settingsTable["TextLabelSizePadY"] = 0
end
if not settingsTable["TextLabelPositionPadY"] then
settingsTable["TextLabelPositionPadY"] = 0
end
if not settingsTable["TextButtonSizePadY"] then
settingsTable["TextButtonSizePadY"] = 12
end
if not settingsTable["TextButtonPositionPadY"] then
settingsTable["TextButtonPositionPadY"] = 2
end
--Wrapper frame takes care of styled objects
local wrapperFrame = Instance.new("Frame")
wrapperFrame.Name = "WrapperFrame"
wrapperFrame.BackgroundTransparency = 1
wrapperFrame.Size = UDim2.new(1,0,1,0)
wrapperFrame.Parent = frame
for i, child in ipairs(guiObjects) do
child.Parent = wrapperFrame
end
local recalculate = function()
wait()
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(recalculate)
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
t.CreateSlider = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 4
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local bar = Instance.new("TextButton")
bar.Text = ""
bar.AutoButtonColor = false
bar.Name = "Bar"
bar.BackgroundColor3 = Color3.new(0,0,0)
if type(width) == "number" then
bar.Size = UDim2.new(0,width,0,5)
else
bar.Size = UDim2.new(0,200,0,5)
end
bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
bar.ZIndex = 2
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/Slider.png"
slider.Position = UDim2.new(0,0,0.5,-10)
slider.Size = UDim2.new(0,20,0,20)
slider.ZIndex = 3
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateSliderNew = function(steps,width,position)
local sliderGui = Instance.new("Frame")
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = "SliderGui"
local sliderSteps = Instance.new("IntValue")
sliderSteps.Name = "SliderSteps"
sliderSteps.Value = steps
sliderSteps.Parent = sliderGui
local areaSoak = Instance.new("TextButton")
areaSoak.Name = "AreaSoak"
areaSoak.Text = ""
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 6
sliderGui.AncestryChanged:connect(function(child,parent)
if parent == nil then
areaSoak.Parent = nil
else
areaSoak.Parent = getScreenGuiAncestor(sliderGui)
end
end)
local sliderPosition = Instance.new("IntValue")
sliderPosition.Name = "SliderPosition"
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local sliderBarImgHeight = 7
local sliderBarCapImgWidth = 4
local bar = Instance.new("ImageButton")
bar.BackgroundTransparency = 1
bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png"
bar.Name = "Bar"
local displayWidth = 200
if type(width) == "number" then
bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight)
displayWidth = width - (sliderBarCapImgWidth * 2)
else
bar.Size = UDim2.new(0,200,0,sliderBarImgHeight)
end
bar.ZIndex = 3
bar.Parent = sliderGui
if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
bar.Position = position
end
local barLeft = bar:clone()
barLeft.Name = "BarLeft"
barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png"
barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight)
barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset)
barLeft.Parent = sliderGui
barLeft.ZIndex = 3
local barRight = barLeft:clone()
barRight.Name = "BarRight"
barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png"
barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset)
barRight.Parent = sliderGui
local fillLeft = barLeft:clone()
fillLeft.Name = "FillLeft"
fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png"
fillLeft.Parent = sliderGui
fillLeft.ZIndex = 4
local fill = fillLeft:clone()
fill.Name = "Fill"
fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png"
fill.Parent = bar
fill.ZIndex = 4
fill.Position = UDim2.new(0, 0, 0, 0)
fill.Size = UDim2.new(0.5, 0, 1, 0)
-- bar.Visible = false
local slider = Instance.new("ImageButton")
slider.Name = "Slider"
slider.BackgroundTransparency = 1
slider.Image = "rbxasset://textures/ui/slider_new_tab.png"
slider.Position = UDim2.new(0,0,0.5,-14)
slider.Size = UDim2.new(0,28,0,28)
slider.ZIndex = 5
slider.Parent = bar
local areaSoakMouseMoveCon = nil
areaSoak.MouseLeave:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
areaSoak.MouseButton1Up:connect(function()
if areaSoak.Visible then
cancelSlide(areaSoak)
end
end)
slider.MouseButton1Down:connect(function()
areaSoak.Visible = true
if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
end)
slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
sliderPosition.Changed:connect(function(prop)
sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
fill.Size = UDim2.new(relativePosX, 0, 1, 0)
end)
bar.MouseButton1Down:connect(function(x,y)
setSliderPos(x,slider,sliderPosition,bar,steps)
end)
return sliderGui, sliderPosition, sliderSteps
end
t.CreateTrueScrollingFrame = function()
local lowY = nil
local highY = nil
local dragCon = nil
local upCon = nil
local internalChange = false
local descendantsChangeConMap = {}
local scrollingFrame = Instance.new("Frame")
scrollingFrame.Name = "ScrollingFrame"
scrollingFrame.Active = true
scrollingFrame.Size = UDim2.new(1,0,1,0)
scrollingFrame.ClipsDescendants = true
local controlFrame = Instance.new("Frame")
controlFrame.Name = "ControlFrame"
controlFrame.BackgroundTransparency = 1
controlFrame.Size = UDim2.new(0,18,1,0)
controlFrame.Position = UDim2.new(1,-20,0,0)
controlFrame.Parent = scrollingFrame
local scrollBottom = Instance.new("BoolValue")
scrollBottom.Value = false
scrollBottom.Name = "ScrollBottom"
scrollBottom.Parent = controlFrame
local scrollUp = Instance.new("BoolValue")
scrollUp.Value = false
scrollUp.Name = "scrollUp"
scrollUp.Parent = controlFrame
local scrollUpButton = Instance.new("TextButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.Text = ""
scrollUpButton.AutoButtonColor = false
scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
scrollUpButton.BorderColor3 = Color3.new(1,1,1)
scrollUpButton.BackgroundTransparency = 0.5
scrollUpButton.Size = UDim2.new(0,18,0,18)
scrollUpButton.ZIndex = 2
scrollUpButton.Parent = controlFrame
for i = 1, 6 do
local triFrame = Instance.new("Frame")
triFrame.BorderColor3 = Color3.new(1,1,1)
triFrame.Name = "tri" .. tostring(i)
triFrame.ZIndex = 3
triFrame.BackgroundTransparency = 0.5
triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
triFrame.Parent = scrollUpButton
end
scrollUpButton.MouseEnter:connect(function()
scrollUpButton.BackgroundTransparency = 0.1
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.1
end
end)
scrollUpButton.MouseLeave:connect(function()
scrollUpButton.BackgroundTransparency = 0.5
local upChildren = scrollUpButton:GetChildren()
for i = 1, #upChildren do
upChildren[i].BackgroundTransparency = 0.5
end
end)
local scrollDownButton = scrollUpButton:clone()
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.Position = UDim2.new(0,0,1,-18)
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
end
scrollDownButton.MouseEnter:connect(function()
scrollDownButton.BackgroundTransparency = 0.1
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.1
end
end)
scrollDownButton.MouseLeave:connect(function()
scrollDownButton.BackgroundTransparency = 0.5
local downChildren = scrollDownButton:GetChildren()
for i = 1, #downChildren do
downChildren[i].BackgroundTransparency = 0.5
end
end)
scrollDownButton.Parent = controlFrame
local scrollTrack = Instance.new("Frame")
scrollTrack.Name = "ScrollTrack"
scrollTrack.BackgroundTransparency = 1
scrollTrack.Size = UDim2.new(0,18,1,-38)
scrollTrack.Position = UDim2.new(0,0,0,19)
scrollTrack.Parent = controlFrame
local scrollbar = Instance.new("TextButton")
scrollbar.BackgroundColor3 = Color3.new(0,0,0)
scrollbar.BorderColor3 = Color3.new(1,1,1)
scrollbar.BackgroundTransparency = 0.5
scrollbar.AutoButtonColor = false
scrollbar.Text = ""
scrollbar.Active = true
scrollbar.Name = "ScrollBar"
scrollbar.ZIndex = 2
scrollbar.BackgroundTransparency = 0.5
scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
scrollbar.Position = UDim2.new(0,0,0,0)
scrollbar.Parent = scrollTrack
local scrollNub = Instance.new("Frame")
scrollNub.Name = "ScrollNub"
scrollNub.BorderColor3 = Color3.new(1,1,1)
scrollNub.Size = UDim2.new(0,10,0,0)
scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
scrollNub.ZIndex = 2
scrollNub.BackgroundTransparency = 0.5
scrollNub.Parent = scrollbar
local newNub = scrollNub:clone()
newNub.Position = UDim2.new(0.5,-5,0.5,-2)
newNub.Parent = scrollbar
local lastNub = scrollNub:clone()
lastNub.Position = UDim2.new(0.5,-5,0.5,2)
lastNub.Parent = scrollbar
scrollbar.MouseEnter:connect(function()
scrollbar.BackgroundTransparency = 0.1
scrollNub.BackgroundTransparency = 0.1
newNub.BackgroundTransparency = 0.1
lastNub.BackgroundTransparency = 0.1
end)
scrollbar.MouseLeave:connect(function()
scrollbar.BackgroundTransparency = 0.5
scrollNub.BackgroundTransparency = 0.5
newNub.BackgroundTransparency = 0.5
lastNub.BackgroundTransparency = 0.5
end)
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local function positionScrollBar(x,y,offset)
local oldPos = scrollbar.Position
if y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
return (oldPos ~= scrollbar.Position)
end
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
return (oldPos ~= scrollbar.Position)
end
local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
if newScaleYPos + relativeSize > 1 then
newScaleYPos = 1 - relativeSize
scrollBottom.Value = true
scrollUp.Value = false
elseif newScaleYPos <= 0 then
newScaleYPos = 0
scrollUp.Value = true
scrollBottom.Value = false
else
scrollUp.Value = false
scrollBottom.Value = false
end
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
return (oldPos ~= scrollbar.Position)
end
local function drillDownSetHighLow(instance)
if not instance or not instance:IsA("GuiObject") then return end
if instance == controlFrame then return end
if instance:IsDescendantOf(controlFrame) then return end
if not instance.Visible then return end
if lowY and lowY > instance.AbsolutePosition.Y then
lowY = instance.AbsolutePosition.Y
elseif not lowY then
lowY = instance.AbsolutePosition.Y
end
if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
local children = instance:GetChildren()
for i = 1, #children do
drillDownSetHighLow(children[i])
end
end
local function resetHighLow()
local firstChildren = scrollingFrame:GetChildren()
for i = 1, #firstChildren do
drillDownSetHighLow(firstChildren[i])
end
end
local function recalculate()
internalChange = true
local percentFrame = 0
if scrollbar.Position.Y.Scale > 0 then
if scrollbar.Visible then
percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
else
percentFrame = 0
end
end
if percentFrame > 0.99 then percentFrame = 1 end
local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
local guiChildren = scrollingFrame:GetChildren()
for i = 1, #guiChildren do
if guiChildren[i] ~= controlFrame then
guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
end
end
lowY = nil
highY = nil
resetHighLow()
internalChange = false
end
local function setSliderSizeAndPosition()
if not highY or not lowY then return end
local totalYSpan = math.abs(highY - lowY)
if totalYSpan == 0 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
return
end
local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
if percentShown >= 1 then
scrollbar.Visible = false
scrollDownButton.Visible = false
scrollUpButton.Visible = false
recalculate()
else
scrollbar.Visible = true
scrollDownButton.Visible = true
scrollUpButton.Visible = true
scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
end
local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
end
if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
end
end
local buttonScrollAmountPixels = 7
local reentrancyGuardScrollUp = false
local function doScrollUp()
if reentrancyGuardScrollUp then return end
reentrancyGuardScrollUp = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollUp = false
end
local reentrancyGuardScrollDown = false
local function doScrollDown()
if reentrancyGuardScrollDown then return end
reentrancyGuardScrollDown = true
if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
recalculate()
end
reentrancyGuardScrollDown = false
end
local function scrollUp(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local function scrollDown(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
scrollbar.MouseButton1Down:connect(function(x,y)
if scrollbar.Active then
scrollStamp = tick()
local mouseOffset = y - scrollbar.AbsolutePosition.y
if dragCon then dragCon:disconnect() dragCon = nil end
if upCon then upCon:disconnect() upCon = nil end
local prevY = y
local reentrancyGuardMouseScroll = false
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
if reentrancyGuardMouseScroll then return end
reentrancyGuardMouseScroll = true
if positionScrollBar(x,y,mouseOffset) then
recalculate()
end
reentrancyGuardMouseScroll = false
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
local function heightCheck(instance)
if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
elseif not highY then
highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
end
setSliderSizeAndPosition()
end
local function highLowRecheck()
local oldLowY = lowY
local oldHighY = highY
lowY = nil
highY = nil
resetHighLow()
if (lowY ~= oldLowY) or (highY ~= oldHighY) then
setSliderSizeAndPosition()
end
end
local function descendantChanged(this, prop)
if internalChange then return end
if not this.Visible then return end
if prop == "Size" or prop == "Position" then
wait()
highLowRecheck()
end
end
scrollingFrame.DescendantAdded:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if instance.Visible then
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end
descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
end)
scrollingFrame.DescendantRemoving:connect(function(instance)
if not instance:IsA("GuiObject") then return end
if descendantsChangeConMap[instance] then
descendantsChangeConMap[instance]:disconnect()
descendantsChangeConMap[instance] = nil
end
wait() -- wait a heartbeat for sizes to reconfig
highLowRecheck()
end)
scrollingFrame.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if not highY or not lowY then return end
highLowRecheck()
setSliderSizeAndPosition()
end
end)
return scrollingFrame, controlFrame
end
t.CreateScrollingFrame = function(orderList,scrollStyle)
local frame = Instance.new("Frame")
frame.Name = "ScrollingFrame"
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1,0,1,0)
local scrollUpButton = Instance.new("ImageButton")
scrollUpButton.Name = "ScrollUpButton"
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
scrollUpButton.Size = UDim2.new(0,17,0,17)
local scrollDownButton = Instance.new("ImageButton")
scrollDownButton.Name = "ScrollDownButton"
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
scrollDownButton.Size = UDim2.new(0,17,0,17)
local scrollbar = Instance.new("ImageButton")
scrollbar.Name = "ScrollBar"
scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
scrollbar.BackgroundTransparency = 1
scrollbar.Size = UDim2.new(0, 18, 0, 150)
local scrollStamp = 0
local scrollDrag = Instance.new("ImageButton")
scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186"
scrollDrag.Size = UDim2.new(1, 0, 0, 16)
scrollDrag.BackgroundTransparency = 1
scrollDrag.Name = "ScrollDrag"
scrollDrag.Active = true
scrollDrag.Parent = scrollbar
local mouseDrag = Instance.new("ImageButton")
mouseDrag.Active = false
mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
mouseDrag.AutoButtonColor = false
mouseDrag.BackgroundTransparency = 1
mouseDrag.Name = "mouseDrag"
mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
mouseDrag.ZIndex = 10
local style = "simple"
if scrollStyle and tostring(scrollStyle) then
style = scrollStyle
end
local scrollPosition = 1
local rowSize = 0
local howManyDisplayed = 0
local layoutGridScrollBar = function()
howManyDisplayed = 0
local guiObjects = {}
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
if scrollPosition < 1 then scrollPosition = 1 end
local totalPixelsY = frame.AbsoluteSize.Y
local pixelsRemainingY = frame.AbsoluteSize.Y
local totalPixelsX = frame.AbsoluteSize.X
local xCounter = 0
local rowSizeCounter = 0
local setRowSize = true
local pixelsBelowScrollbar = 0
local pos = #guiObjects
local currentRowY = 0
pos = scrollPosition
--count up from current scroll position to fill out grid
while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
--previous pos was the end of a row
if xCounter >= totalPixelsX then
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
xCounter = guiObjects[pos].AbsoluteSize.X
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos + 1
end
--Count wherever current row left off
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
currentRowY = 0
pos = scrollPosition - 1
xCounter = 0
--objects with varying X,Y dimensions can rarely cause minor errors
--rechecking every new scrollPosition is necessary to avoid 100% of errors
--count backwards from current scrollPosition to see if we can add more rows
while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
rowSizeCounter = rowSizeCounter + 1
if xCounter >= totalPixelsX then
rowSize = rowSizeCounter - 1
rowSizeCounter = 0
xCounter = guiObjects[pos].AbsoluteSize.X
if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
if scrollPosition <= rowSize then
scrollPosition = 1
break
else
scrollPosition = scrollPosition - rowSize
end
currentRowY = 0
else
break
end
end
if guiObjects[pos].AbsoluteSize.Y > currentRowY then
currentRowY = guiObjects[pos].AbsoluteSize.Y
end
pos = pos - 1
end
--Do check last time if pos = 0
if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
scrollPosition = 1
end
xCounter = 0
--pos = scrollPosition
rowSizeCounter = 0
setRowSize = true
local lastChildSize = 0
local xOffset,yOffset = 0
if guiObjects[1] then
yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
end
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemainingY < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
if xCounter + child.AbsoluteSize.X >= totalPixelsX then
if setRowSize then
rowSize = rowSizeCounter - 1
setRowSize = false
end
xCounter = 0
pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
end
child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
xCounter = xCounter + child.AbsoluteSize.X
child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
if child.Visible then
howManyDisplayed = howManyDisplayed + 1
end
lastChildSize = child.AbsoluteSize
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
if lastChildSize == 0 then
scrollDownButton.Active = false
else
scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
end
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local layoutSimpleScrollBar = function()
local guiObjects = {}
howManyDisplayed = 0
if orderList then
for i, child in ipairs(orderList) do
if child.Parent == frame then
table.insert(guiObjects, child)
end
end
else
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollDrag.Active = false
scrollPosition = 1
return
end
if scrollPosition > #guiObjects then
scrollPosition = #guiObjects
end
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
local pixelsBelowScrollbar = 0
local pos = #guiObjects
while pixelsBelowScrollbar < totalPixels and pos >= 1 do
if pos >= scrollPosition then
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
else
if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
if scrollPosition <= 1 then
scrollPosition = 1
break
else
--local ("Backing up ScrollPosition from -- " ..scrollPosition)
scrollPosition = scrollPosition - 1
end
else
break
end
end
pos = pos - 1
end
pos = scrollPosition
for i, child in ipairs(guiObjects) do
if i < scrollPosition then
--print("Hiding " .. child.Name)
child.Visible = false
else
if pixelsRemaining < 0 then
--print("Out of Space " .. child.Name)
child.Visible = false
else
--print("Laying out " .. child.Name)
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
if (pixelsRemaining >= 0) then
child.Visible = true
howManyDisplayed = howManyDisplayed + 1
else
child.Visible = false
end
end
end
end
scrollUpButton.Active = (scrollPosition > 1)
scrollDownButton.Active = (pixelsRemaining < 0)
scrollDrag.Active = #guiObjects > howManyDisplayed
scrollDrag.Visible = scrollDrag.Active
end
local moveDragger = function()
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
if not scrollDrag.Parent then return end
local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
if dragSizeY < 16 then dragSizeY = 16 end
scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
if relativeYPos > 1 then relativeYPos = 1
elseif relativeYPos < 0 then relativeYPos = 0 end
local absYPos = 0
if relativeYPos ~= 0 then
absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
end
scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
end
local reentrancyGuard = false
local recalculate = function()
if reentrancyGuard then
return
end
reentrancyGuard = true
wait()
local success, err = nil
if style == "grid" then
success, err = pcall(function() layoutGridScrollBar() end)
elseif style == "simple" then
success, err = pcall(function() layoutSimpleScrollBar() end)
end
if not success then print(err) end
moveDragger()
reentrancyGuard = false
end
local doScrollUp = function()
scrollPosition = (scrollPosition) - rowSize
if scrollPosition < 1 then scrollPosition = 1 end
recalculate(nil)
end
local doScrollDown = function()
scrollPosition = (scrollPosition) + rowSize
recalculate(nil)
end
local scrollUp = function(mouseYPos)
if scrollUpButton.Active then
scrollStamp = tick()
local current = scrollStamp
local upCon
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
upCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollUp()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollUp()
if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
break
end
if not scrollUpButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local scrollDown = function(mouseYPos)
if scrollDownButton.Active then
scrollStamp = tick()
local current = scrollStamp
local downCon
downCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
downCon:disconnect()
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
doScrollDown()
wait(0.2)
local t = tick()
local w = 0.1
while scrollStamp == current do
doScrollDown()
if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
break
end
if not scrollDownButton.Active then break end
if tick()-t > 5 then
w = 0
elseif tick()-t > 2 then
w = 0.06
end
wait(w)
end
end
end
local y = 0
scrollDrag.MouseButton1Down:connect(function(x,y)
if scrollDrag.Active then
scrollStamp = tick()
local mouseOffset = y - scrollDrag.AbsolutePosition.y
local dragCon
local upCon
dragCon = mouseDrag.MouseMoved:connect(function(x,y)
local barAbsPos = scrollbar.AbsolutePosition.y
local barAbsSize = scrollbar.AbsoluteSize.y
local dragAbsSize = scrollDrag.AbsoluteSize.y
local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
y = y - mouseOffset
y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
y = y - barAbsPos
local guiObjects = 0
local children = frame:GetChildren()
if children then
for i, child in ipairs(children) do
if child:IsA("GuiObject") then
guiObjects = guiObjects + 1
end
end
end
local doublePercent = y/(barAbsSize-dragAbsSize)
local rowDiff = rowSize
local totalScrollCount = guiObjects - (howManyDisplayed - 1)
local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
if newScrollPosition < scrollPosition then
rowDiff = -rowDiff
end
if newScrollPosition < 1 then
newScrollPosition = 1
end
scrollPosition = newScrollPosition
recalculate(nil)
end)
upCon = mouseDrag.MouseButton1Up:connect(function()
scrollStamp = tick()
mouseDrag.Parent = nil
dragCon:disconnect(); dragCon = nil
upCon:disconnect(); drag = nil
end)
mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
end
end)
local scrollMouseCount = 0
scrollUpButton.MouseButton1Down:connect(
function()
scrollUp()
end)
scrollUpButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollDownButton.MouseButton1Down:connect(
function()
scrollDown()
end)
scrollbar.MouseButton1Up:connect(function()
scrollStamp = tick()
end)
scrollbar.MouseButton1Down:connect(
function(x,y)
if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
scrollDown(y)
elseif y < (scrollDrag.AbsolutePosition.y) then
scrollUp(y)
end
end)
frame.ChildAdded:connect(function()
recalculate(nil)
end)
frame.ChildRemoved:connect(function()
recalculate(nil)
end)
frame.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
--Wait a heartbeat for it to sync in
recalculate(nil)
end
end)
frame.AncestryChanged:connect(function() recalculate(nil) end)
return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
end
local function binaryGrow(min, max, fits)
if min > max then
return min
end
local biggestLegal = min
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
biggestLegal = mid
--Try growing
min = mid + 1
else
--Doesn't fit, shrink
max = mid - 1
end
end
return biggestLegal
end
local function binaryShrink(min, max, fits)
if min > max then
return min
end
local smallestLegal = max
while min <= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
smallestLegal = mid
--It fits, shrink
max = mid - 1
else
--Doesn't fit, grow
min = mid + 1
end
end
return smallestLegal
end
local function getGuiOwner(instance)
while instance ~= nil do
if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
return instance
end
instance = instance.Parent
end
return nil
end
t.AutoTruncateTextObject = function(textLabel)
local text = textLabel.Text
local fullLabel = textLabel:Clone()
fullLabel.Name = "Full" .. textLabel.Name
fullLabel.BorderSizePixel = 0
fullLabel.BackgroundTransparency = 0
fullLabel.Text = text
fullLabel.TextXAlignment = Enum.TextXAlignment.Center
fullLabel.Position = UDim2.new(0,-3,0,0)
fullLabel.Size = UDim2.new(0,100,1,0)
fullLabel.Visible = false
fullLabel.Parent = textLabel
local shortText = nil
local mouseEnterConnection = nil
local mouseLeaveConnection= nil
local checkForResize = function()
if getGuiOwner(textLabel) == nil then
return
end
textLabel.Text = text
if textLabel.TextFits then
--Tear down the rollover if it is active
if mouseEnterConnection then
mouseEnterConnection:disconnect()
mouseEnterConnection = nil
end
if mouseLeaveConnection then
mouseLeaveConnection:disconnect()
mouseLeaveConnection = nil
end
else
local len = string.len(text)
textLabel.Text = text .. "~"
--Shrink the text
local textSize = binaryGrow(0, len,
function(pos)
if pos == 0 then
textLabel.Text = "~"
else
textLabel.Text = string.sub(text, 1, pos) .. "~"
end
return textLabel.TextFits
end)
shortText = string.sub(text, 1, textSize) .. "~"
textLabel.Text = shortText
--Make sure the fullLabel fits
if not fullLabel.TextFits then
--Already too small, grow it really bit to start
fullLabel.Size = UDim2.new(0, 10000, 1, 0)
end
--Okay, now try to binary shrink it back down
local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
function(size)
fullLabel.Size = UDim2.new(0, size, 1, 0)
return fullLabel.TextFits
end)
fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
--Now setup the rollover effects, if they are currently off
if mouseEnterConnection == nil then
mouseEnterConnection = textLabel.MouseEnter:connect(
function()
fullLabel.ZIndex = textLabel.ZIndex + 1
fullLabel.Visible = true
--textLabel.Text = ""
end)
end
if mouseLeaveConnection == nil then
mouseLeaveConnection = textLabel.MouseLeave:connect(
function()
fullLabel.Visible = false
--textLabel.Text = shortText
end)
end
end
end
textLabel.AncestryChanged:connect(checkForResize)
textLabel.Changed:connect(
function(prop)
if prop == "AbsoluteSize" then
checkForResize()
end
end)
checkForResize()
local function changeText(newText)
text = newText
fullLabel.Text = text
checkForResize()
end
return textLabel, changeText
end
local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
if fromPage then
fromPage.Visible = false
if transitionFrame.Visible == false then
transitionFrame.Size = fromPage.Size
transitionFrame.Position = fromPage.Position
end
else
if transitionFrame.Visible == false then
transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
end
end
transitionFrame.Visible = true
currentPageValue.Value = nil
local newsize, newPosition
if toPage then
--Make it visible so it resizes
toPage.Visible = true
newSize = toPage.Size
newPosition = toPage.Position
toPage.Visible = false
else
newSize = UDim2.new(0.0,50,0.0,50)
newPosition = UDim2.new(0.5,-25,0.5,-25)
end
transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
function(state)
if state == Enum.TweenStatus.Completed then
transitionFrame.Visible = false
if toPage then
toPage.Visible = true
currentPageValue.Value = toPage
end
end
end)
end
t.CreateTutorial = function(name, tutorialKey, createButtons)
local frame = Instance.new("Frame")
frame.Name = "Tutorial-" .. name
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
local transitionFrame = Instance.new("Frame")
transitionFrame.Name = "TransitionFrame"
transitionFrame.Style = Enum.FrameStyle.RobloxRound
transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
transitionFrame.Visible = false
transitionFrame.Parent = frame
local currentPageValue = Instance.new("ObjectValue")
currentPageValue.Name = "CurrentTutorialPage"
currentPageValue.Value = nil
currentPageValue.Parent = frame
local boolValue = Instance.new("BoolValue")
boolValue.Name = "Buttons"
boolValue.Value = createButtons
boolValue.Parent = frame
local pages = Instance.new("Frame")
pages.Name = "Pages"
pages.BackgroundTransparency = 1
pages.Size = UDim2.new(1,0,1,0)
pages.Parent = frame
local function getVisiblePageAndHideOthers()
local visiblePage = nil
local children = pages:GetChildren()
if children then
for i,child in ipairs(children) do
if child.Visible then
if visiblePage then
child.Visible = false
else
visiblePage = child
end
end
end
end
return visiblePage
end
local showTutorial = function(alwaysShow)
if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
print("Showing tutorial-",tutorialKey)
local currentTutorialPage = getVisiblePageAndHideOthers()
local firstPage = pages:FindFirstChild("TutorialPage1")
if firstPage then
TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
else
error("Could not find TutorialPage1")
end
end
end
local dismissTutorial = function()
local currentTutorialPage = getVisiblePageAndHideOthers()
if currentTutorialPage then
TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
end
UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
end
local gotoPage = function(pageNum)
local page = pages:FindFirstChild("TutorialPage" .. pageNum)
local currentTutorialPage = getVisiblePageAndHideOthers()
TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
end
return frame, showTutorial, dismissTutorial, gotoPage
end
local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
local frame = Instance.new("Frame")
frame.Name = "TutorialPage"
frame.Style = Enum.FrameStyle.RobloxRound
frame.Size = UDim2.new(0.6, 0, 0.6, 0)
frame.Position = UDim2.new(0.2, 0, 0.2, 0)
frame.Visible = false
local frameHeader = Instance.new("TextLabel")
frameHeader.Name = "Header"
frameHeader.Text = name
frameHeader.BackgroundTransparency = 1
frameHeader.FontSize = Enum.FontSize.Size24
frameHeader.Font = Enum.Font.ArialBold
frameHeader.TextColor3 = Color3.new(1,1,1)
frameHeader.TextXAlignment = Enum.TextXAlignment.Center
frameHeader.TextWrap = true
frameHeader.Size = UDim2.new(1,-55, 0, 22)
frameHeader.Position = UDim2.new(0,0,0,0)
frameHeader.Parent = frame
local skipButton = Instance.new("ImageButton")
skipButton.Name = "SkipButton"
skipButton.AutoButtonColor = false
skipButton.BackgroundTransparency = 1
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
skipButton.MouseButton1Click:connect(function()
skipTutorial()
end)
skipButton.MouseEnter:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
end)
skipButton.MouseLeave:connect(function()
skipButton.Image = "rbxasset://textures/ui/closeButton.png"
end)
skipButton.Size = UDim2.new(0, 25, 0, 25)
skipButton.Position = UDim2.new(1, -25, 0, 0)
skipButton.Parent = frame
if giveDoneButton then
local doneButton = Instance.new("TextButton")
doneButton.Name = "DoneButton"
doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
doneButton.Text = "Done"
doneButton.TextColor3 = Color3.new(1,1,1)
doneButton.Font = Enum.Font.ArialBold
doneButton.FontSize = Enum.FontSize.Size18
doneButton.Size = UDim2.new(0,100,0,50)
doneButton.Position = UDim2.new(0.5,-50,1,-50)
if skipTutorial then
doneButton.MouseButton1Click:connect(function() skipTutorial() end)
end
doneButton.Parent = frame
end
local innerFrame = Instance.new("Frame")
innerFrame.Name = "ContentFrame"
innerFrame.BackgroundTransparency = 1
innerFrame.Position = UDim2.new(0,0,0,25)
innerFrame.Parent = frame
local nextButton = Instance.new("TextButton")
nextButton.Name = "NextButton"
nextButton.Text = "Next"
nextButton.TextColor3 = Color3.new(1,1,1)
nextButton.Font = Enum.Font.Arial
nextButton.FontSize = Enum.FontSize.Size18
nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
nextButton.Size = UDim2.new(0,80, 0, 32)
nextButton.Position = UDim2.new(0.5, 5, 1, -32)
nextButton.Active = false
nextButton.Visible = false
nextButton.Parent = frame
local prevButton = Instance.new("TextButton")
prevButton.Name = "PrevButton"
prevButton.Text = "Previous"
prevButton.TextColor3 = Color3.new(1,1,1)
prevButton.Font = Enum.Font.Arial
prevButton.FontSize = Enum.FontSize.Size18
prevButton.Style = Enum.ButtonStyle.RobloxButton
prevButton.Size = UDim2.new(0,80, 0, 32)
prevButton.Position = UDim2.new(0.5, -85, 1, -32)
prevButton.Active = false
prevButton.Visible = false
prevButton.Parent = frame
if giveDoneButton then
innerFrame.Size = UDim2.new(1,0,1,-75)
else
innerFrame.Size = UDim2.new(1,0,1,-22)
end
local parentConnection = nil
local function basicHandleResize()
if frame.Visible and frame.Parent then
local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
handleResize(200,maxSize)
end
end
frame.Changed:connect(
function(prop)
if prop == "Parent" then
if parentConnection ~= nil then
parentConnection:disconnect()
parentConnection = nil
end
if frame.Parent and frame.Parent:IsA("GuiObject") then
parentConnection = frame.Parent.Changed:connect(
function(parentProp)
if parentProp == "AbsoluteSize" then
wait()
basicHandleResize()
end
end)
basicHandleResize()
end
end
if prop == "Visible" then
basicHandleResize()
end
end)
return frame, innerFrame
end
t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
local frame = nil
local contentFrame = nil
local textLabel = Instance.new("TextLabel")
textLabel.BackgroundTransparency = 1
textLabel.TextColor3 = Color3.new(1,1,1)
textLabel.Text = text
textLabel.TextWrap = true
textLabel.TextXAlignment = Enum.TextXAlignment.Left
textLabel.TextYAlignment = Enum.TextYAlignment.Center
textLabel.Font = Enum.Font.Arial
textLabel.FontSize = Enum.FontSize.Size14
textLabel.Size = UDim2.new(1,0,1,0)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
frame.Size = UDim2.new(0, size, 0, size)
return textLabel.TextFits
end)
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
textLabel.Parent = contentFrame
return frame
end
t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
local frame = nil
local contentFrame = nil
local imageLabel = Instance.new("ImageLabel")
imageLabel.BackgroundTransparency = 1
imageLabel.Image = imageAsset
imageLabel.Size = UDim2.new(0,x,0,y)
imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
local function handleResize(minSize, maxSize)
size = binaryShrink(minSize, maxSize,
function(size)
return size >= x and size >= y
end)
if size >= x and size >= y then
imageLabel.Size = UDim2.new(0,x, 0,y)
imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
else
if x > y then
--X is limiter, so
imageLabel.Size = UDim2.new(1,0,y/x,0)
imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
else
--Y is limiter
imageLabel.Size = UDim2.new(x/y,0,1, 0)
imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
end
end
size = size + 50
frame.Size = UDim2.new(0, size, 0, size)
frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
end
frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
imageLabel.Parent = contentFrame
return frame
end
t.AddTutorialPage = function(tutorial, tutorialPage)
local transitionFrame = tutorial.TransitionFrame
local currentPageValue = tutorial.CurrentTutorialPage
if not tutorial.Buttons.Value then
tutorialPage.NextButton.Parent = nil
tutorialPage.PrevButton.Parent = nil
end
local children = tutorial.Pages:GetChildren()
if children and #children > 0 then
tutorialPage.Name = "TutorialPage" .. (#children+1)
local previousPage = children[#children]
if not previousPage:IsA("GuiObject") then
error("All elements under Pages must be GuiObjects")
end
if tutorial.Buttons.Value then
if previousPage.NextButton.Active then
error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
end
previousPage.NextButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
end)
previousPage.NextButton.Active = true
previousPage.NextButton.Visible = true
if tutorialPage.PrevButton.Active then
error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
end
tutorialPage.PrevButton.MouseButton1Click:connect(
function()
TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
end)
tutorialPage.PrevButton.Active = true
tutorialPage.PrevButton.Visible = true
end
tutorialPage.Parent = tutorial.Pages
else
--First child
tutorialPage.Name = "TutorialPage1"
tutorialPage.Parent = tutorial.Pages
end
end
t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
if not userIdsForSets then
error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
end
if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
end
if not objectSelected then
error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
end
if type(objectSelected) ~= "function" then
error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
end
if dialogClosed and type(dialogClosed) ~= "function" then
error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
end
if showAdminCategories == nil then -- by default, don't show beta sets
showAdminCategories = false
end
local arrayPosition = 1
local insertButtons = {}
local insertButtonCons = {}
local contents = nil
local setGui = nil
-- used for water selections
local waterForceDirection = "NegX"
local waterForce = "None"
local waterGui, waterTypeChangedEvent = nil
local Data = {}
Data.CurrentCategory = nil
Data.Category = {}
local SetCache = {}
local userCategoryButtons = nil
local buttonWidth = 64
local buttonHeight = buttonWidth
local SmallThumbnailUrl = nil
local LargeThumbnailUrl = nil
local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
if useAssetVersionId then
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
else
LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
end
local function drillDownSetZIndex(parent, index)
local children = parent:GetChildren()
for i = 1, #children do
if children[i]:IsA("GuiObject") then
children[i].ZIndex = index
end
drillDownSetZIndex(children[i], index)
end
end
-- for terrain stamping
local currTerrainDropDownFrame = nil
local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
local terrainShapeMap = {}
for i = 1, #terrainShapes do
terrainShapeMap[terrainShapes[i]] = i - 1
end
terrainShapeMap[terrainShapes[#terrainShapes]] = 6
local function createWaterGui()
local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
local waterFrame = Instance.new("Frame")
waterFrame.Name = "WaterFrame"
waterFrame.Style = Enum.FrameStyle.RobloxSquare
waterFrame.Size = UDim2.new(0,150,0,110)
waterFrame.Visible = false
local waterForceLabel = Instance.new("TextLabel")
waterForceLabel.Name = "WaterForceLabel"
waterForceLabel.BackgroundTransparency = 1
waterForceLabel.Size = UDim2.new(1,0,0,12)
waterForceLabel.Font = Enum.Font.ArialBold
waterForceLabel.FontSize = Enum.FontSize.Size12
waterForceLabel.TextColor3 = Color3.new(1,1,1)
waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
waterForceLabel.Text = "Water Force"
waterForceLabel.Parent = waterFrame
local waterForceDirLabel = waterForceLabel:Clone()
waterForceDirLabel.Name = "WaterForceDirectionLabel"
waterForceDirLabel.Text = "Water Force Direction"
waterForceDirLabel.Position = UDim2.new(0,0,0,50)
waterForceDirLabel.Parent = waterFrame
local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
local waterForceDirectionSelectedFunc = function(newForceDirection)
waterForceDirection = newForceDirection
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceSelectedFunc = function(newForce)
waterForce = newForce
waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
end
local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
forceWaterDirectionSelection("NegX")
waterForceDirectionDropDown.Parent = waterForceDirLabel
local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
forceWaterForceSelection("None")
waterForceDropDown.Size = UDim2.new(1,0,0,25)
waterForceDropDown.Position = UDim2.new(0,0,1,3)
waterForceDropDown.Parent = waterForceLabel
return waterFrame, waterTypeChangedEvent
end
-- Helper Function that contructs gui elements
local function createSetGui()
local setGui = Instance.new("ScreenGui")
setGui.Name = "SetGui"
local setPanel = Instance.new("Frame")
setPanel.Name = "SetPanel"
setPanel.Active = true
setPanel.BackgroundTransparency = 1
if position then
setPanel.Position = position
else
setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
end
if size then
setPanel.Size = size
else
setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
end
setPanel.Style = Enum.FrameStyle.RobloxRound
setPanel.ZIndex = 6
setPanel.Parent = setGui
-- Children of SetPanel
local itemPreview = Instance.new("Frame")
itemPreview.Name = "ItemPreview"
itemPreview.BackgroundTransparency = 1
itemPreview.Position = UDim2.new(0.8,5,0.085,0)
itemPreview.Size = UDim2.new(0.21,0,0.9,0)
itemPreview.ZIndex = 6
itemPreview.Parent = setPanel
-- Children of ItemPreview
local textPanel = Instance.new("Frame")
textPanel.Name = "TextPanel"
textPanel.BackgroundTransparency = 1
textPanel.Position = UDim2.new(0,0,0.45,0)
textPanel.Size = UDim2.new(1,0,0.55,0)
textPanel.ZIndex = 6
textPanel.Parent = itemPreview
-- Children of TextPanel
local rolloverText = Instance.new("TextLabel")
rolloverText.Name = "RolloverText"
rolloverText.BackgroundTransparency = 1
rolloverText.Size = UDim2.new(1,0,0,48)
rolloverText.ZIndex = 6
rolloverText.Font = Enum.Font.ArialBold
rolloverText.FontSize = Enum.FontSize.Size24
rolloverText.Text = ""
rolloverText.TextColor3 = Color3.new(1,1,1)
rolloverText.TextWrap = true
rolloverText.TextXAlignment = Enum.TextXAlignment.Left
rolloverText.TextYAlignment = Enum.TextYAlignment.Top
rolloverText.Parent = textPanel
local largePreview = Instance.new("ImageLabel")
largePreview.Name = "LargePreview"
largePreview.BackgroundTransparency = 1
largePreview.Image = ""
largePreview.Size = UDim2.new(1,0,0,170)
largePreview.ZIndex = 6
largePreview.Parent = itemPreview
local sets = Instance.new("Frame")
sets.Name = "Sets"
sets.BackgroundTransparency = 1
sets.Position = UDim2.new(0,0,0,5)
sets.Size = UDim2.new(0.23,0,1,-5)
sets.ZIndex = 6
sets.Parent = setPanel
-- Children of Sets
local line = Instance.new("Frame")
line.Name = "Line"
line.BackgroundColor3 = Color3.new(1,1,1)
line.BackgroundTransparency = 0.7
line.BorderSizePixel = 0
line.Position = UDim2.new(1,-3,0.06,0)
line.Size = UDim2.new(0,3,0.9,0)
line.ZIndex = 6
line.Parent = sets
local setsLists, controlFrame = t.CreateTrueScrollingFrame()
setsLists.Size = UDim2.new(1,-6,0.94,0)
setsLists.Position = UDim2.new(0,0,0.06,0)
setsLists.BackgroundTransparency = 1
setsLists.Name = "SetsLists"
setsLists.ZIndex = 6
setsLists.Parent = sets
drillDownSetZIndex(controlFrame, 7)
local setsHeader = Instance.new("TextLabel")
setsHeader.Name = "SetsHeader"
setsHeader.BackgroundTransparency = 1
setsHeader.Size = UDim2.new(0,47,0,24)
setsHeader.ZIndex = 6
setsHeader.Font = Enum.Font.ArialBold
setsHeader.FontSize = Enum.FontSize.Size24
setsHeader.Text = "Sets"
setsHeader.TextColor3 = Color3.new(1,1,1)
setsHeader.TextXAlignment = Enum.TextXAlignment.Left
setsHeader.TextYAlignment = Enum.TextYAlignment.Top
setsHeader.Parent = sets
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(1,-32,0,-2)
cancelButton.Size = UDim2.new(0,34,0,34)
cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
cancelButton.ZIndex = 6
cancelButton.Text = ""
cancelButton.Modal = true
cancelButton.Parent = setPanel
-- Children of Cancel Button
local cancelImage = Instance.new("ImageLabel")
cancelImage.Name = "CancelImage"
cancelImage.BackgroundTransparency = 1
cancelImage.Image = "http://www.roblox.com/asset/?id=54135717"
cancelImage.Position = UDim2.new(0,-2,0,-2)
cancelImage.Size = UDim2.new(0,16,0,16)
cancelImage.ZIndex = 6
cancelImage.Parent = cancelButton
return setGui
end
local function createSetButton(text)
local setButton = Instance.new("TextButton")
if text then setButton.Text = text
else setButton.Text = "" end
setButton.AutoButtonColor = false
setButton.BackgroundTransparency = 1
setButton.BackgroundColor3 = Color3.new(1,1,1)
setButton.BorderSizePixel = 0
setButton.Size = UDim2.new(1,-5,0,18)
setButton.ZIndex = 6
setButton.Visible = false
setButton.Font = Enum.Font.Arial
setButton.FontSize = Enum.FontSize.Size18
setButton.TextColor3 = Color3.new(1,1,1)
setButton.TextXAlignment = Enum.TextXAlignment.Left
return setButton
end
local function buildSetButton(name, setId, setImageId, i, count)
local button = createSetButton(name)
button.Text = name
button.Name = "SetButton"
button.Visible = true
local setValue = Instance.new("IntValue")
setValue.Name = "SetId"
setValue.Value = setId
setValue.Parent = button
local setName = Instance.new("StringValue")
setName.Name = "SetName"
setName.Value = name
setName.Parent = button
return button
end
local function processCategory(sets)
local setButtons = {}
local numSkipped = 0
for i = 1, #sets do
if not showAdminCategories and sets[i].Name == "Beta" then
numSkipped = numSkipped + 1
else
setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
end
end
return setButtons
end
local function handleResize()
wait() -- neccessary to insure heartbeat happened
local itemPreview = setGui.SetPanel.ItemPreview
itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
end
local function makeInsertAssetButton()
local insertAssetButtonExample = Instance.new("Frame")
insertAssetButtonExample.Name = "InsertAssetButtonExample"
insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
insertAssetButtonExample.BackgroundTransparency = 1
insertAssetButtonExample.ZIndex = 6
insertAssetButtonExample.Visible = false
local assetId = Instance.new("IntValue")
assetId.Name = "AssetId"
assetId.Value = 0
assetId.Parent = insertAssetButtonExample
local assetName = Instance.new("StringValue")
assetName.Name = "AssetName"
assetName.Value = ""
assetName.Parent = insertAssetButtonExample
local button = Instance.new("TextButton")
button.Name = "Button"
button.Text = ""
button.Style = Enum.ButtonStyle.RobloxButton
button.Position = UDim2.new(0.025,0,0.025,0)
button.Size = UDim2.new(0.95,0,0.95,0)
button.ZIndex = 6
button.Parent = insertAssetButtonExample
local buttonImage = Instance.new("ImageLabel")
buttonImage.Name = "ButtonImage"
buttonImage.Image = ""
buttonImage.Position = UDim2.new(0,-7,0,-7)
buttonImage.Size = UDim2.new(1,14,1,14)
buttonImage.BackgroundTransparency = 1
buttonImage.ZIndex = 7
buttonImage.Parent = button
local configIcon = buttonImage:clone()
configIcon.Name = "ConfigIcon"
configIcon.Visible = false
configIcon.Position = UDim2.new(1,-23,1,-24)
configIcon.Size = UDim2.new(0,16,0,16)
configIcon.Image = ""
configIcon.ZIndex = 6
configIcon.Parent = insertAssetButtonExample
return insertAssetButtonExample
end
local function showLargePreview(insertButton)
if insertButton:FindFirstChild("AssetId") then
delay(0,function()
game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
end)
end
if insertButton:FindFirstChild("AssetName") then
setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
end
end
local function selectTerrainShape(shape)
if currTerrainDropDownFrame then
objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
end
end
local function createTerrainTypeButton(name, parent)
local dropDownTextButton = Instance.new("TextButton")
dropDownTextButton.Name = name .. "Button"
dropDownTextButton.Font = Enum.Font.ArialBold
dropDownTextButton.FontSize = Enum.FontSize.Size14
dropDownTextButton.BorderSizePixel = 0
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
dropDownTextButton.Text = name
dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.ZIndex = parent.ZIndex + 1
dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
dropDownTextButton.Position = UDim2.new(0,1,0,0)
dropDownTextButton.MouseEnter:connect(function()
dropDownTextButton.BackgroundTransparency = 0
dropDownTextButton.TextColor3 = Color3.new(0,0,0)
end)
dropDownTextButton.MouseLeave:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
end)
dropDownTextButton.MouseButton1Click:connect(function()
dropDownTextButton.BackgroundTransparency = 1
dropDownTextButton.TextColor3 = Color3.new(1,1,1)
if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
dropDownTextButton.Parent.Visible = false
end
selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
end)
return dropDownTextButton
end
local function createTerrainDropDownMenu(zIndex)
local dropDown = Instance.new("Frame")
dropDown.Name = "TerrainDropDown"
dropDown.BackgroundColor3 = Color3.new(0,0,0)
dropDown.BorderColor3 = Color3.new(1,0,0)
dropDown.Size = UDim2.new(0,200,0,0)
dropDown.Visible = false
dropDown.ZIndex = zIndex
dropDown.Parent = setGui
for i = 1, #terrainShapes do
local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
shapeButton.Parent = dropDown
dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
end
dropDown.MouseLeave:connect(function()
dropDown.Visible = false
end)
end
local function createDropDownMenuButton(parent)
local dropDownButton = Instance.new("ImageButton")
dropDownButton.Name = "DropDownButton"
dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509"
dropDownButton.BackgroundTransparency = 1
dropDownButton.Size = UDim2.new(0,16,0,16)
dropDownButton.Position = UDim2.new(1,-24,0,6)
dropDownButton.ZIndex = parent.ZIndex + 2
dropDownButton.Parent = parent
if not setGui:FindFirstChild("TerrainDropDown") then
createTerrainDropDownMenu(8)
end
dropDownButton.MouseButton1Click:connect(function()
setGui.TerrainDropDown.Visible = true
setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
currTerrainDropDownFrame = parent
end)
end
local function buildInsertButton()
local insertButton = makeInsertAssetButton()
insertButton.Name = "InsertAssetButton"
insertButton.Visible = true
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
createDropDownMenuButton(insertButton)
end
local lastEnter = nil
local mouseEnterCon = insertButton.MouseEnter:connect(function()
lastEnter = insertButton
delay(0.1,function()
if lastEnter == insertButton then
showLargePreview(insertButton)
end
end)
end)
return insertButton, mouseEnterCon
end
local function realignButtonGrid(columns)
local x = 0
local y = 0
for i = 1, #insertButtons do
insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
x = x + 1
if x >= columns then
x = 0
y = y + 1
end
end
end
local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
if visible then
insertFrame.AssetName.Value = name
insertFrame.AssetId.Value = assetId
local newImageUrl = SmallThumbnailUrl .. assetId
if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
delay(0,function()
game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
if insertFrame:findFirstChild("Button") then
insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
end
end)
end
table.insert(insertButtonCons,
insertFrame.Button.MouseButton1Click:connect(function()
-- special case for water, show water selection gui
local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
waterGui.Visible = isWaterSelected
if isWaterSelected then
objectSelected(name, tonumber(assetId), nil)
else
objectSelected(name, tonumber(assetId))
end
end)
)
insertFrame.Visible = true
else
insertFrame.Visible = false
end
end
local function loadSectionOfItems(setGui, rows, columns)
local pageSize = rows * columns
if arrayPosition > #contents then return end
local origArrayPos = arrayPosition
local yCopy = 0
for i = 1, pageSize + 1 do
if arrayPosition >= #contents + 1 then
break
end
local buttonCon
insertButtons[arrayPosition], buttonCon = buildInsertButton()
table.insert(insertButtonCons,buttonCon)
insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
arrayPosition = arrayPosition + 1
end
realignButtonGrid(columns)
local indexCopy = origArrayPos
for index = origArrayPos, arrayPosition do
if insertButtons[index] then
if contents[index] then
-- we don't want water to have a drop down button
if contents[index].Name == "Water" then
if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
end
end
local assetId
if useAssetVersionId then
assetId = contents[index].AssetVersionId
else
assetId = contents[index].AssetId
end
setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
else
break
end
else
break
end
indexCopy = index
end
end
local function setSetIndex()
Data.Category[Data.CurrentCategory].Index = 0
rows = 7
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
contents = Data.Category[Data.CurrentCategory].Contents
if contents then
-- remove our buttons and their connections
for i = 1, #insertButtons do
insertButtons[i]:remove()
end
for i = 1, #insertButtonCons do
if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
end
insertButtonCons = {}
insertButtons = {}
arrayPosition = 1
loadSectionOfItems(setGui, rows, columns)
end
end
local function selectSet(button, setName, setId, setIndex)
if button and Data.Category[Data.CurrentCategory] ~= nil then
if button ~= Data.Category[Data.CurrentCategory].Button then
Data.Category[Data.CurrentCategory].Button = button
if SetCache[setId] == nil then
SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
end
Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
Data.Category[Data.CurrentCategory].SetName = setName
Data.Category[Data.CurrentCategory].SetId = setId
end
setSetIndex()
end
end
local function selectCategoryPage(buttons, page)
if buttons ~= Data.CurrentCategory then
if Data.CurrentCategory then
for key, button in pairs(Data.CurrentCategory) do
button.Visible = false
end
end
Data.CurrentCategory = buttons
if Data.Category[Data.CurrentCategory] == nil then
Data.Category[Data.CurrentCategory] = {}
if #buttons > 0 then
selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
end
else
Data.Category[Data.CurrentCategory].Button = nil
selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
end
end
end
local function selectCategory(category)
selectCategoryPage(category, 0)
end
local function resetAllSetButtonSelection()
local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
for i = 1, #setButtons do
if setButtons[i]:IsA("TextButton") then
setButtons[i].Selected = false
setButtons[i].BackgroundTransparency = 1
setButtons[i].TextColor3 = Color3.new(1,1,1)
setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
end
end
end
local function populateSetsFrame()
local currRow = 0
for i = 1, #userCategoryButtons do
local button = userCategoryButtons[i]
button.Visible = true
button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
button.Parent = setGui.SetPanel.Sets.SetsLists
if i == 1 then -- we will have this selected by default, so show it
button.Selected = true
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
end
button.MouseEnter:connect(function()
if not button.Selected then
button.BackgroundTransparency = 0
button.TextColor3 = Color3.new(0,0,0)
end
end)
button.MouseLeave:connect(function()
if not button.Selected then
button.BackgroundTransparency = 1
button.TextColor3 = Color3.new(1,1,1)
end
end)
button.MouseButton1Click:connect(function()
resetAllSetButtonSelection()
button.Selected = not button.Selected
button.BackgroundColor3 = Color3.new(0,204/255,0)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
end)
currRow = currRow + 1
end
local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
-- set first category as loaded for default
if buttons then
for i = 1, #buttons do
if buttons[i]:IsA("TextButton") then
selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
selectCategory(userCategoryButtons)
break
end
end
end
end
setGui = createSetGui()
waterGui, waterTypeChangedEvent = createWaterGui()
waterGui.Position = UDim2.new(0,55,0,0)
waterGui.Parent = setGui
setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
if prop == "AbsoluteSize" then
handleResize()
setSetIndex()
end
end)
local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
scrollFrame.Name = "ItemsFrame"
scrollFrame.ZIndex = 6
scrollFrame.Parent = setGui.SetPanel
scrollFrame.BackgroundTransparency = 1
drillDownSetZIndex(controlFrame,7)
controlFrame.Parent = setGui.SetPanel
controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
local debounce = false
controlFrame.ScrollBottom.Changed:connect(function(prop)
if controlFrame.ScrollBottom.Value == true then
if debounce then return end
debounce = true
loadSectionOfItems(setGui, rows, columns)
debounce = false
end
end)
local userData = {}
for id = 1, #userIdsForSets do
local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
if newUserData and #newUserData > 2 then
-- start at #3 to skip over My Decals and My Models for each account
for category = 3, #newUserData do
if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
table.insert(userData,1,newUserData[category])
else
table.insert(userData, newUserData[category])
end
end
end
end
if userData then
userCategoryButtons = processCategory(userData)
end
rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
populateSetsFrame()
insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
setGui.SetPanel.Visible = false
if dialogClosed then dialogClosed() end
end)
local setVisibilityFunction = function(visible)
if visible then
setGui.SetPanel.Visible = true
else
setGui.SetPanel.Visible = false
end
end
local getVisibilityFunction = function()
if setGui then
if setGui:FindFirstChild("SetPanel") then
return setGui.SetPanel.Visible
end
end
return false
end
return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
end
t.CreateTerrainMaterialSelector = function(size,position)
local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
local selectedButton = nil
local frame = Instance.new("Frame")
frame.Name = "TerrainMaterialSelector"
if size then
frame.Size = size
else
frame.Size = UDim2.new(0, 245, 0, 230)
end
if position then
frame.Position = position
end
frame.BorderSizePixel = 0
frame.BackgroundColor3 = Color3.new(0,0,0)
frame.Active = true
terrainMaterialSelectionChanged.Parent = frame
local waterEnabled = true -- todo: turn this on when water is ready
local materialToImageMap = {}
local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
if waterEnabled then
table.insert(materialNames,"Water")
end
local currentMaterial = 1
function getEnumFromName(choice)
if choice == "Grass" then return 1 end
if choice == "Sand" then return 2 end
if choice == "Erase" then return 0 end
if choice == "Brick" then return 3 end
if choice == "Granite" then return 4 end
if choice == "Asphalt" then return 5 end
if choice == "Iron" then return 6 end
if choice == "Aluminum" then return 7 end
if choice == "Gold" then return 8 end
if choice == "Plank" then return 9 end
if choice == "Log" then return 10 end
if choice == "Gravel" then return 11 end
if choice == "Cinder Block" then return 12 end
if choice == "Stone Wall" then return 13 end
if choice == "Concrete" then return 14 end
if choice == "Plastic (red)" then return 15 end
if choice == "Plastic (blue)" then return 16 end
if choice == "Water" then return 17 end
end
function getNameFromEnum(choice)
if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
if waterEnabled then
if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
end
end
local function updateMaterialChoice(choice)
currentMaterial = getEnumFromName(choice)
terrainMaterialSelectionChanged:Fire(currentMaterial)
end
-- we so need a better way to do this
for i,v in pairs(materialNames) do
materialToImageMap[v] = {}
if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112"
elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652"
elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537"
elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153"
elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038"
elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093"
elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995"
elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118"
elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848"
elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924"
elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015"
elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051"
elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206"
elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103"
elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804"
elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059"
elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474"
else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!!
end
end
local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
scrollFrame.Size = UDim2.new(0.85,0,1,0)
scrollFrame.Position = UDim2.new(0,0,0,0)
scrollFrame.Parent = frame
scrollUp.Parent = frame
scrollUp.Visible = true
scrollUp.Position = UDim2.new(1,-19,0,0)
scrollDown.Parent = frame
scrollDown.Visible = true
scrollDown.Position = UDim2.new(1,-19,1,-17)
local function goToNewMaterial(buttonWrap, materialName)
updateMaterialChoice(materialName)
buttonWrap.BackgroundTransparency = 0
selectedButton.BackgroundTransparency = 1
selectedButton = buttonWrap
end
local function createMaterialButton(name)
local buttonWrap = Instance.new("TextButton")
buttonWrap.Text = ""
buttonWrap.Size = UDim2.new(0,32,0,32)
buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
buttonWrap.BorderSizePixel = 0
buttonWrap.BackgroundTransparency = 1
buttonWrap.AutoButtonColor = false
buttonWrap.Name = tostring(name)
local imageButton = Instance.new("ImageButton")
imageButton.AutoButtonColor = false
imageButton.BackgroundTransparency = 1
imageButton.Size = UDim2.new(0,30,0,30)
imageButton.Position = UDim2.new(0,1,0,1)
imageButton.Name = tostring(name)
imageButton.Parent = buttonWrap
imageButton.Image = materialToImageMap[name].Regular
local enumType = Instance.new("NumberValue")
enumType.Name = "EnumType"
enumType.Parent = buttonWrap
enumType.Value = 0
imageButton.MouseEnter:connect(function()
buttonWrap.BackgroundTransparency = 0
end)
imageButton.MouseLeave:connect(function()
if selectedButton ~= buttonWrap then
buttonWrap.BackgroundTransparency = 1
end
end)
imageButton.MouseButton1Click:connect(function()
if selectedButton ~= buttonWrap then
goToNewMaterial(buttonWrap, tostring(name))
end
end)
return buttonWrap
end
for i = 1, #materialNames do
local imageButton = createMaterialButton(materialNames[i])
if materialNames[i] == "Grass" then -- always start with grass as the default
selectedButton = imageButton
imageButton.BackgroundTransparency = 0
end
imageButton.Parent = scrollFrame
end
local forceTerrainMaterialSelection = function(newMaterialType)
if not newMaterialType then return end
if currentMaterial == newMaterialType then return end
local matName = getNameFromEnum(newMaterialType)
local buttons = scrollFrame:GetChildren()
for i = 1, #buttons do
if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
if string.find(buttons[i].Name, matName) then
goToNewMaterial(buttons[i],matName)
return
end
end
end
frame.Changed:connect(function ( prop )
if prop == "AbsoluteSize" then
recalculateScroll()
end
end)
recalculateScroll()
return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
end
t.CreateLoadingFrame = function(name,size,position)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053")
local loadingFrame = Instance.new("Frame")
loadingFrame.Name = "LoadingFrame"
loadingFrame.Style = Enum.FrameStyle.RobloxRound
if size then loadingFrame.Size = size
else loadingFrame.Size = UDim2.new(0,300,0,160) end
if position then loadingFrame.Position = position
else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
local loadingBar = Instance.new("Frame")
loadingBar.Name = "LoadingBar"
loadingBar.BackgroundColor3 = Color3.new(0,0,0)
loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
loadingBar.Position = UDim2.new(0,0,0,41)
loadingBar.Size = UDim2.new(1,0,0,30)
loadingBar.Parent = loadingFrame
local loadingGreenBar = Instance.new("ImageLabel")
loadingGreenBar.Name = "LoadingGreenBar"
loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053"
loadingGreenBar.Position = UDim2.new(0,0,0,0)
loadingGreenBar.Size = UDim2.new(0,0,1,0)
loadingGreenBar.Visible = false
loadingGreenBar.Parent = loadingBar
local loadingPercent = Instance.new("TextLabel")
loadingPercent.Name = "LoadingPercent"
loadingPercent.BackgroundTransparency = 1
loadingPercent.Position = UDim2.new(0,0,1,0)
loadingPercent.Size = UDim2.new(1,0,0,14)
loadingPercent.Font = Enum.Font.Arial
loadingPercent.Text = "0%"
loadingPercent.FontSize = Enum.FontSize.Size14
loadingPercent.TextColor3 = Color3.new(1,1,1)
loadingPercent.Parent = loadingBar
local cancelButton = Instance.new("TextButton")
cancelButton.Name = "CancelButton"
cancelButton.Position = UDim2.new(0.5,-60,1,-40)
cancelButton.Size = UDim2.new(0,120,0,40)
cancelButton.Font = Enum.Font.Arial
cancelButton.FontSize = Enum.FontSize.Size18
cancelButton.TextColor3 = Color3.new(1,1,1)
cancelButton.Text = "Cancel"
cancelButton.Style = Enum.ButtonStyle.RobloxButton
cancelButton.Parent = loadingFrame
local loadingName = Instance.new("TextLabel")
loadingName.Name = "loadingName"
loadingName.BackgroundTransparency = 1
loadingName.Size = UDim2.new(1,0,0,18)
loadingName.Position = UDim2.new(0,0,0,2)
loadingName.Font = Enum.Font.Arial
loadingName.Text = name
loadingName.TextColor3 = Color3.new(1,1,1)
loadingName.TextStrokeTransparency = 1
loadingName.FontSize = Enum.FontSize.Size18
loadingName.Parent = loadingFrame
local cancelButtonClicked = Instance.new("BindableEvent")
cancelButtonClicked.Name = "CancelButtonClicked"
cancelButtonClicked.Parent = cancelButton
cancelButton.MouseButton1Click:connect(function()
cancelButtonClicked:Fire()
end)
local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
if percent and type(percent) ~= "number" then
error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
end
local newSize = nil
if percent < 0 then
newSize = UDim2.new(0,0,1,0)
elseif percent > 1 then
newSize = UDim2.new(1,0,1,0)
else
newSize = UDim2.new(percent,0,1,0)
end
if tweenAction then
if not tweenLength then
error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
end
if (newSize.X.Scale > 0) then
loadingGreenBar.Visible = true
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true)
else
loadingGreenBar:TweenSize( newSize,
Enum.EasingDirection.Out,
Enum.EasingStyle.Quad,
tweenLength,
true,
function()
if (newSize.X.Scale < 0) then
loadingGreenBar.Visible = false
end
end)
end
else
loadingGreenBar.Size = newSize
loadingGreenBar.Visible = (newSize.X.Scale > 0)
end
end
loadingGreenBar.Changed:connect(function(prop)
if prop == "Size" then
loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
end
end)
return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
end
t.CreatePluginFrame = function (name,size,position,scrollable,parent)
function createMenuButton(size,position,text,fontsize,name,parent)
local button = Instance.new("TextButton",parent)
button.AutoButtonColor = false
button.Name = name
button.BackgroundTransparency = 1
button.Position = position
button.Size = size
button.Font = Enum.Font.ArialBold
button.FontSize = fontsize
button.Text = text
button.TextColor3 = Color3.new(1,1,1)
button.BorderSizePixel = 0
button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
button.MouseEnter:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function ( )
if button.Selected then return end
button.BackgroundTransparency = 1
end)
return button
end
local dragBar = Instance.new("Frame",parent)
dragBar.Name = tostring(name) .. "DragBar"
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
dragBar.BorderColor3 = Color3.new(0,0,0)
if size then
dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
else
dragBar.Size = UDim2.new(0,183,0,20)
end
if position then
dragBar.Position = position
end
dragBar.Active = true
dragBar.Draggable = true
--dragBar.Visible = false
dragBar.MouseEnter:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
end)
dragBar.MouseLeave:connect(function ( )
dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end)
-- plugin name label
local pluginNameLabel = Instance.new("TextLabel",dragBar)
pluginNameLabel.Name = "BarNameLabel"
pluginNameLabel.Text = " " .. tostring(name)
pluginNameLabel.TextColor3 = Color3.new(1,1,1)
pluginNameLabel.TextStrokeTransparency = 0
pluginNameLabel.Size = UDim2.new(1,0,1,0)
pluginNameLabel.Font = Enum.Font.ArialBold
pluginNameLabel.FontSize = Enum.FontSize.Size18
pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
pluginNameLabel.BackgroundTransparency = 1
-- close button
local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
local closeEvent = Instance.new("BindableEvent")
closeEvent.Name = "CloseEvent"
closeEvent.Parent = closeButton
closeButton.MouseButton1Click:connect(function ()
closeEvent:Fire()
closeButton.BackgroundTransparency = 1
end)
-- help button
local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
local helpFrame = Instance.new("Frame",dragBar)
helpFrame.Name = "HelpFrame"
helpFrame.BackgroundColor3 = Color3.new(0,0,0)
helpFrame.Size = UDim2.new(0,300,0,552)
helpFrame.Position = UDim2.new(1,5,0,0)
helpFrame.Active = true
helpFrame.BorderSizePixel = 0
helpFrame.Visible = false
helpButton.MouseButton1Click:connect(function( )
helpFrame.Visible = not helpFrame.Visible
if helpFrame.Visible then
helpButton.Selected = true
helpButton.BackgroundTransparency = 0
local screenGui = getScreenGuiAncestor(helpFrame)
if screenGui then
if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
else -- position on right hand side
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpFrame.Position = UDim2.new(1,5,0,0)
end
else
helpButton.Selected = false
helpButton.BackgroundTransparency = 1
end
end)
local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
local minimizeFrame = Instance.new("Frame",dragBar)
minimizeFrame.Name = "MinimizeFrame"
minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
minimizeFrame.BorderColor3 = Color3.new(0,0,0)
minimizeFrame.Position = UDim2.new(0,0,1,0)
if size then
minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
else
minimizeFrame.Size = UDim2.new(0,183,0,50)
end
minimizeFrame.Visible = false
local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
minimizeBigButton.Name = "MinimizeButton"
minimizeBigButton.Size = UDim2.new(0,100,0,40)
minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
minimizeBigButton.Font = Enum.Font.ArialBold
minimizeBigButton.FontSize = Enum.FontSize.Size18
minimizeBigButton.TextColor3 = Color3.new(1,1,1)
minimizeBigButton.Text = "Show"
local separatingLine = Instance.new("Frame",dragBar)
separatingLine.Name = "SeparatingLine"
separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
separatingLine.BorderSizePixel = 0
separatingLine.Position = UDim2.new(1,-18,0.5,-7)
separatingLine.Size = UDim2.new(0,1,0,14)
local otherSeparatingLine = separatingLine:clone()
otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
otherSeparatingLine.Parent = dragBar
local widgetContainer = Instance.new("Frame",dragBar)
widgetContainer.Name = "WidgetContainer"
widgetContainer.BackgroundTransparency = 1
widgetContainer.Position = UDim2.new(0,0,1,0)
widgetContainer.BorderColor3 = Color3.new(0,0,0)
if not scrollable then
widgetContainer.BackgroundTransparency = 0
widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
end
if size then
if scrollable then
widgetContainer.Size = size
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
end
else
if scrollable then
widgetContainer.Size = UDim2.new(0,163,0,400)
else
widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
end
end
if position then
widgetContainer.Position = position + UDim2.new(0,0,0,20)
end
local frame,control,verticalDragger = nil
if scrollable then
--frame for widgets
frame,control = t.CreateTrueScrollingFrame()
frame.Size = UDim2.new(1, 0, 1, 0)
frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
frame.BorderColor3 = Color3.new(0,0,0)
frame.Active = true
frame.Parent = widgetContainer
control.Parent = dragBar
control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
control.BorderSizePixel = 0
control.BackgroundTransparency = 0
control.Position = UDim2.new(1,-21,1,1)
if size then
control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
else
control.Size = UDim2.new(0,21,0,400)
end
control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
local fakeLine = Instance.new("Frame",control)
fakeLine.Name = "FakeLine"
fakeLine.BorderSizePixel = 0
fakeLine.BackgroundColor3 = Color3.new(0,0,0)
fakeLine.Size = UDim2.new(0,1,1,1)
fakeLine.Position = UDim2.new(1,0,0,0)
verticalDragger = Instance.new("TextButton",widgetContainer)
verticalDragger.ZIndex = 2
verticalDragger.AutoButtonColor = false
verticalDragger.Name = "VerticalDragger"
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
verticalDragger.BorderColor3 = Color3.new(0,0,0)
verticalDragger.Size = UDim2.new(1,20,0,20)
verticalDragger.Position = UDim2.new(0,0,1,0)
verticalDragger.Active = true
verticalDragger.Text = ""
local scrubFrame = Instance.new("Frame",verticalDragger)
scrubFrame.Name = "ScrubFrame"
scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
scrubFrame.BorderSizePixel = 0
scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
scrubFrame.Size = UDim2.new(0,10,0,1)
scrubFrame.ZIndex = 5
local scrubTwo = scrubFrame:clone()
scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
scrubTwo.Parent = verticalDragger
local scrubThree = scrubFrame:clone()
scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
scrubThree.Parent = verticalDragger
local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
areaSoak.Name = "AreaSoak"
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.BackgroundTransparency = 1
areaSoak.BorderSizePixel = 0
areaSoak.Text = ""
areaSoak.ZIndex = 10
areaSoak.Visible = false
areaSoak.Active = true
local draggingVertical = false
local startYPos = nil
verticalDragger.MouseEnter:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
end)
verticalDragger.MouseLeave:connect(function ()
verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
end)
verticalDragger.MouseButton1Down:connect(function(x,y)
draggingVertical = true
areaSoak.Visible = true
startYPos = y
end)
areaSoak.MouseButton1Up:connect(function ( )
draggingVertical = false
areaSoak.Visible = false
end)
areaSoak.MouseMoved:connect(function(x,y)
if not draggingVertical then return end
local yDelta = y - startYPos
if not control.ScrollDownButton.Visible and yDelta > 0 then
return
end
if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
control.Size = UDim2.new (0,21,0,150)
return
end
startYPos = y
if widgetContainer.Size.Y.Offset + yDelta >= 0 then
widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
end
end)
end
local function switchMinimize()
minimizeFrame.Visible = not minimizeFrame.Visible
if scrollable then
frame.Visible = not frame.Visible
verticalDragger.Visible = not verticalDragger.Visible
control.Visible = not control.Visible
else
widgetContainer.Visible = not widgetContainer.Visible
end
if minimizeFrame.Visible then
minimizeButton.Text = "+"
else
minimizeButton.Text = "-"
end
end
minimizeBigButton.MouseButton1Click:connect(function ( )
switchMinimize()
end)
minimizeButton.MouseButton1Click:connect(function( )
switchMinimize()
end)
if scrollable then
return dragBar, frame, helpFrame, closeEvent
else
return dragBar, widgetContainer, helpFrame, closeEvent
end
end
t.Help =
function(funcNameOrFunc)
--input argument can be a string or a function. Should return a description (of arguments and expected side effects)
if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
return "Function CreatePropertyDropDownMenu. " ..
"Arguments: (instance, propertyName, enumType). " ..
"Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
end
if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
return "Function CreateDropDownMenu. " ..
"Arguments: (items, onItemSelected). " ..
"Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
end
if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
return "Function CreateMessageDialog. " ..
"Arguments: (title, message, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
end
if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
return "Function CreateStyledMessageDialog. " ..
"Arguments: (title, message, style, buttons). " ..
"Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
end
if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
return "Function GetFontHeight. " ..
"Arguments: (font, fontSize). " ..
"Side effect: returns the size in pixels of the given font + fontSize"
end
if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
end
if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
return "Function CreateScrollingFrame. " ..
"Arguments: (orderList, style) " ..
"Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
end
if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
return "Function CreateTrueScrollingFrame. " ..
"Arguments: (nil) " ..
"Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
end
if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
return "Function AutoTruncateTextObject. " ..
"Arguments: (textLabel) " ..
"Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
end
if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
return "Function CreateSlider. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then
return "Function CreateSliderNew. " ..
"Arguments: (steps, width, position) " ..
"Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
end
if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
return "Function CreateLoadingFrame. " ..
"Arguments: (name, size, position) " ..
"Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
end
if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
return "Function CreateTerrainMaterialSelector. " ..
"Arguments: (size, position) " ..
"Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
end
end
--rbxsig%CqCG5zfc/XIjIEri/nYJ9ncJ3CVrBvc+dEV0dQ0iMjszaG45Oo0mMObtk/wOX16pMnwFbOo5OEnl4hHRNHan3AfjuqIGQGvXAnkfpO9PC3aX9Ekw8Y86aje2lzBqi4eikB6dWdf/Zfh/RORnavUxn3htyTMVZmaAd/Qc6eNOAc4=%
--rbxassetid%48488235%
--new playerlist by Zach Lindblad (fusroblox)
--contact him for any revisions/issues
--------------------
-- Super Util
--------------------
local ADMINS =
{
iagoMAO = "rbxasset://textures/ui/admins/iagoMAO.png",
winsupermario1234 = "rbxasset://textures/ui/admins/winsupermario1234.png",
Carrot = "rbxasset://textures/ui/admins/carrot.png",
coke = "rbxasset://textures/ui/admins/coke.png",
khanglegos = "rbxasset://textures/ui/admins/khanglegos.png",
QuackIAttack = "rbxasset://textures/ui/admins/QuackIAttack.png",
romulo27 = "rbxasset://textures/ui/admins/romulo27.png",
TheLivingBee = "rbxasset://textures/ui/admins/TheLivingBee.png",
OliverA = 1,
kinery = 1,
Peridorky =1,
Bitl = "rbxasset://textures/ui/admins/bitl.png",
Raymonf = "rbxasset://textures/ui/admins/Raymonf.png",
}
--[[
Generic object Create function, which I am using to create Gui's
Thanks to Stravant!
--]]
local Obj = {}
function Obj.Create(guiType)
return function(data)
local obj = Instance.new(guiType)
for k, v in pairs(data) do
if type(k) == 'number' then
v.Parent = obj
else
obj[k] = v
end
end
return obj
end
end
--[[
makes a full sized background for a guiobject
@Args:
imgName asset name of image to fill background
@Return: background gui object
--]]
function MakeBackgroundGuiObj(imgName)
return Obj.Create'ImageLabel'
{
Name = 'Background',
BackgroundTransparency = 1,
Image = imgName,
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(1,0,1,0),
}
end
--[[ turns 255 integer color value to a color3 --]]
function Color3I(r,g,b)
return Color3.new(r/255,g/255,b/255)
end
--[[
Gets correct icon for builder's club status to display by name
@Args:
membershipType Enum of membership status
@Return: string of image asset
--]]
function getMembershipTypeIcon(membershipType,playerName)
if ADMINS[playerName]~=nil then
if ADMINS[playerName] == 1 then
return "rbxasset://textures/ui/admins/default.png"
else
return ADMINS[playerName]
end
elseif membershipType == Enum.MembershipType.None then
return ""
elseif membershipType == Enum.MembershipType.BuildersClub then
return "rbxasset://textures/ui/TinyBcIcon.png"
elseif membershipType == Enum.MembershipType.TurboBuildersClub then
return "rbxasset://textures/ui/TinyTbcIcon.png"
elseif membershipType == Enum.MembershipType.OutrageousBuildersClub then
return "rbxasset://textures/ui/TinyObcIcon.png"
else
error("Unknown membershipType" .. membershipType)
end
end
local function getFriendStatusIcon(friendStatus)
if friendStatus == Enum.FriendStatus.Unknown or friendStatus == Enum.FriendStatus.NotFriend then
return ""
elseif friendStatus == Enum.FriendStatus.Friend then
return "rbxasset://textures/ui/friend.png"
elseif friendStatus == Enum.FriendStatus.FriendRequestSent then
return "rbxasset://textures/ui/friendrequestsent.png"
elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then
return "rbxasset://textures/ui/friendrequestreceived.png"
else
error("Unknown FriendStatus: " .. friendStatus)
end
end
--[[
Utility function to create buttons for the popup menus
@Args:
nparent what to parent this button to
ntext text to put on this button
index number index of this entry in menu
last is this the last element of the popup menu
@Return: a popup menu button
--]]
function MakePopupButton(nparent,ntext,index,last)
local tobj = Obj.Create"ImageButton"
{
Name = 'ReportButton',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,1*index,0),
Size = UDim2.new(1, 0, 1, 0),
ZIndex=9,
Obj.Create'TextLabel'
{
Name = 'ButtonText',
BackgroundTransparency = 1,
Position = UDim2.new(.07, 0, .07, 0),
Size = UDim2.new(.86,0,.86,0),
Parent = HeaderFrame,
Font = 'ArialBold',
Text = ntext,
FontSize = 'Size14',
TextScaled = true,
TextColor3 = Color3.new(1,1,1),
TextStrokeTransparency = 1,
ZIndex=9,
},
Parent = nparent,
}
if index==0 then
tobj.Image = 'http://www.roblox.com/asset/?id=97108784'
elseif last then
tobj.Image = 'http://www.roblox.com/asset/?id=97109175'
else
if index%2==1 then
tobj.Image = 'http://www.roblox.com/asset/?id=97112126'
else
tobj.Image = 'http://www.roblox.com/asset/?id=97109338'
end
end
return tobj
end
--[[
obligatory wait for child function
@Args:
parent Parent object to look for child in
child name of child object to look for
@Return: object waited for
--]]
function WaitForChild(parent,child)
while not parent:FindFirstChild(child) do
wait() debugprint(" child "..parent.Name.." waiting for "..child)
end
return parent[child]
end
---------------------------
-- Workspace Objects
---------------------------
-- might want to move all this to an init function, wait for localplayer elsewhere
local Players = game:GetService('Players')
-- make sure this doesn't run on the server(it will if you dont do this)
while not Players.LocalPlayer do
Players.Changed:wait()
end
local LocalPlayer = Players.LocalPlayer
local Mouse = LocalPlayer:GetMouse()
local ScreenGui = Obj.Create"Frame"
{
Name = 'PlayerListScreen',
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
Parent = script.Parent -- LocalPlayer.PlayerGui -- use for switching into playergui mode
}
local MainFrame = Obj.Create"Frame"
{
Name = 'LeaderBoardFrame',
Position = UDim2.new(1, -150, 0.005, 0),
Size = UDim2.new(0, 150, 0, 800),
BackgroundTransparency = 1,
Parent = ScreenGui,
}
--frame used for expanding leaderstats when frame is 'focused'
local FocusFrame = Obj.Create"Frame"
{
Name = 'FocusFrame',
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(1, 0, 0, 100),
BackgroundTransparency = 1,
Active = true,
Parent = MainFrame,
}
local TemplateFrameYSize = 0.670000017
-- HEADER
local HeaderFrame = Obj.Create"Frame"
{
Name = 'Header',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,0,0),
Size = UDim2.new(1, 0, .07, 0),
Parent = MainFrame,
MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94692054'),
}
local HeaderFrameHeight = HeaderFrame.Size.Y.Scale
local MaximizeButton = Obj.Create"ImageButton"
{
Name = 'MaximizeButton',
Active = true,
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(1,0,1,0),
Parent = HeaderFrame,
}
local HeaderName = Obj.Create"TextLabel"
{
Name = 'PlayerName',
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, .01, 0),
Size = UDim2.new(.98,0,.38,0),
Parent = HeaderFrame,
Font = 'ArialBold',
Text = LocalPlayer.Name,
FontSize='Size24',
--TextScaled = true,
TextColor3 = Color3.new(1,1,1),
TextStrokeColor3 = Color3.new(0,0,0),
TextStrokeTransparency = 0,
TextXAlignment = 'Right',
TextYAlignment = 'Center',
}
local HeaderScore = Obj.Create"TextLabel"
{
Name = 'PlayerScore',
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, .4, 0),
Size = UDim2.new(.98,0,0,30),
Parent = HeaderFrame,
Font = 'ArialBold',
Text = '',
FontSize='Size24',
TextYAlignment = 'Top',
--TextScaled = true,
TextColor3 = Color3.new(1,1,1),
TextStrokeTransparency = 1,
TextXAlignment = 'Right',
TextYAlignment = 'Top',
}
-- BOTTOM
--used for shifting bottom frame for mouse over effects
local BottomShiftFrame = Obj.Create"Frame"
{
Name= 'BottomShiftFrame',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,HeaderFrameHeight,0),
Size = UDim2.new(1,0,1,0),
Parent=MainFrame,
}
local BottomFrame = Obj.Create"Frame"
{
Name = 'Bottom',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,.07,0),
Size = UDim2.new(1, 0, .03, 0),
Parent = BottomShiftFrame,
MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94754966'),
}
local ExtendButton = Obj.Create"ImageButton"
{
Name = 'bigbutton',
Active = true,
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(1,0,1.5,0),
ZIndex = 3,
Parent = BottomFrame,
}
local ExtendTab = Obj.Create"ImageButton"
{
Name = 'extendTab',
Active = true,
BackgroundTransparency = 1,
Image = 'http://www.roblox.com/asset/?id=94692731',
Position = UDim2.new(.608, 0, .3, 0),
Size = UDim2.new(.3,0,.7,0),
Parent = BottomFrame,
}
local TopClipFrame = Obj.Create"Frame"
{
Name = 'ListFrame',
BackgroundTransparency = 1,
Position = UDim2.new(-1,0,.07,0),
Size = UDim2.new(2, 0, 1, 0),
Parent = MainFrame,
ClipsDescendants = true,
}
local BottomClipFrame = Obj.Create"Frame"
{
Name = 'BottomFrame',
BackgroundTransparency = 1,
Position = UDim2.new(0,0, - .8,0),
Size = UDim2.new(1, 0, 1, 0),
Parent = TopClipFrame,
ClipsDescendants = true,
}
local ScrollBarFrame = Obj.Create"Frame"
{
Name = 'ScrollBarFrame',
BackgroundTransparency = 1,
Position = UDim2.new(.987,0,.8,0),
Size = UDim2.new(.01, 0, .2, 0),
Parent = BottomClipFrame,
}
local ScrollBar = Obj.Create"Frame"
{
Name = 'ScrollBar',
BackgroundTransparency = 0,
BackgroundColor3 = Color3.new(.2,.2,.2),
Position = UDim2.new(0,0,0,0),
Size = UDim2.new(1, 0, .5, 0),
ZIndex = 5,
Parent = ScrollBarFrame,
}
local ListFrame = Obj.Create"Frame"
{
Name = 'SubFrame',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,.8,0),
Size = UDim2.new(1, 0, 1, 0),
Parent = BottomClipFrame,
}
local PopUpClipFrame = Obj.Create"Frame"
{
Name = 'PopUpFrame',
BackgroundTransparency = 1,
SizeConstraint='RelativeXX',
Position = MainFrame.Position + UDim2.new( 0,-150,0,0),
Size = UDim2.new(0,150,0,800),
Parent = MainFrame,
ClipsDescendants = true,
ZIndex=9,
}
local PopUpPanel = Obj.Create"Frame"
{
Name = 'Panel',
BackgroundTransparency = 1,
Position = UDim2.new(1,0,0,0),
Size = UDim2.new(1,0,.032,0),
Parent = PopUpClipFrame,
}
local ReportPlayerButton = MakePopupButton(PopUpPanel,'Report Player',0)
local FriendPlayerButton = MakePopupButton(PopUpPanel,'Friend',1,true)
local PersonalServerPanel = Obj.Create"Frame"
{
Name = 'Panel',
BackgroundTransparency = 1,
Position = UDim2.new(1,0,0,0),
Size = UDim2.new(1,0,.032,0),
Parent = PopUpClipFrame,
}
local PSReportPlayerButton = MakePopupButton(PersonalServerPanel,'Report Player',0)
local PSFriendPlayerButton = MakePopupButton(PersonalServerPanel,'Friend',1)
local BanPlayerButton = MakePopupButton(PersonalServerPanel,'Ban',2)
local VisitorButton = MakePopupButton(PersonalServerPanel,'Visitor',3)
local MemberButton = MakePopupButton(PersonalServerPanel,'Member',4)
local AdminButton = MakePopupButton(PersonalServerPanel,'Admin',5,true)
local StatTitles = Obj.Create"Frame"
{
Name = 'StatTitles',
BackgroundTransparency = 1,
Position = UDim2.new(0,0,1,-10),
Size = UDim2.new(1, 0, 0, 0),
Parent = HeaderFrame,
}
local IsMinimized = Instance.new('BoolValue')
local IsMaximized = Instance.new('BoolValue')
local IsTabified = Instance.new('BoolValue')
local AreNamesExpanded = Instance.new('BoolValue')
local MiddleTemplate = Obj.Create"Frame"
{
Name = 'MidTemplate',
BackgroundTransparency = 1,
Position = UDim2.new(100,0,.07,0),
Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0),
Obj.Create'ImageLabel'
{
Name = 'BCLabel',
Active = true,
BackgroundTransparency = 1,
Position = UDim2.new(.005, 5, .20, 0),
Size = UDim2.new(0,16,0,16),
SizeConstraint = 'RelativeYY',
Image = "",
ZIndex = 3,
},
Obj.Create'ImageLabel'
{
Name = 'FriendLabel',
Active = true,
BackgroundTransparency = 1,
Position = UDim2.new(.005, 5, .15, 0),
Size = UDim2.new(0,16,0,16),
SizeConstraint = 'RelativeYY',
Image = "",
ZIndex = 3,
},
Obj.Create"ImageButton"
{
Name = 'ClickListener',
Active = true,
BackgroundTransparency = 1,
Position = UDim2.new(.005, 1, 0, 0),
Size = UDim2.new(.96,0,1,0),
ZIndex = 3,
},
Obj.Create"Frame"
{
Name = 'TitleFrame',
BackgroundTransparency = 1,
Position = UDim2.new(.01, 0, 0, 0),
Size = UDim2.new(0,140,1,0),
ClipsDescendants=true,
Obj.Create"TextLabel"
{
Name = 'Title',
BackgroundTransparency = 1,
Position = UDim2.new(0, 5, 0, 0),
Size = UDim2.new(100,0,1,0),
Font = 'Arial',
FontSize='Size14',
TextColor3 = Color3.new(1,1,1),
TextXAlignment = 'Left',
TextYAlignment = 'Center',
ZIndex = 3,
},
},
Obj.Create"TextLabel"
{
Name = 'PlayerScore',
BackgroundTransparency = 1,
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(1,0,1,0),
Font = 'Arial',
Text = '',
FontSize='Size14',
TextColor3 = Color3.new(1,1,1),
TextXAlignment = 'Left',
TextYAlignment = 'Center',
ZIndex = 3,
},
--Obj.Create'IntValue'{Name = 'ID'},
--Obj.Create'ObjectValue'{Name = 'Player'},
--Obj.Create'IntValue'{Name = 'Score'},
ZIndex = 3,
}
local MiddleBGTemplate = Obj.Create"Frame"
{
Name = 'MidBGTemplate',
BackgroundTransparency = 1,
Position = UDim2.new(100,0,.07,0),
Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0),
MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94692025'),
}
-- REPORT ABUSE OBJECTS
local ReportAbuseShield = Obj.Create"TextButton"
{
Name = "ReportAbuseShield",
Text = "",
AutoButtonColor = false,
Active = true,
Visible = true,
Size = UDim2.new(1,0,1,0),
BackgroundColor3 = Color3I(51,51,51),
BorderColor3 = Color3I(27,42,53),
BackgroundTransparency = 1,
}
local ReportAbuseFrame = Obj.Create "Frame"
{
Name = "Settings",
Position = UDim2.new(0.5, - 250, 0.5, - 200),
Size = UDim2.new(0.0, 500, 0.0, 400),
BackgroundTransparency = 1,
Active = true,
Parent = ReportAbuseShield,
}
local AbuseSettingsFrame = Obj.Create"Frame"
{
Name = "ReportAbuseStyle",
Size = UDim2.new(1, 0, 1, 0),
Active = true,
BackgroundTransparency = 1,
MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96488767'), -- 96480351'),
Obj.Create"TextLabel"
{
Name = "Title",
Text = "Report Abuse",
TextColor3 = Color3I(221,221,221),
Position = UDim2.new(0.5, 0, 0, 30),
Font = Enum.Font.ArialBold,
FontSize = Enum.FontSize.Size36,
},
Obj.Create"TextLabel"
{
Name = "Description",
Text = "This will send a complete report to a moderator. The moderator will review the chat log and take appropriate action.",
TextColor3 = Color3I(221,221,221),
Position = UDim2.new(.01, 0, 0, 55),
Size = UDim2.new(.99, 0, 0, 40),
BackgroundTransparency = 1,
Font = Enum.Font.Arial,
FontSize = Enum.FontSize.Size18,
TextWrap = true,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Top,
},
Obj.Create"TextLabel"
{
Name = "AbuseLabel",
Text = "What did they do?",
Font = Enum.Font.Arial,
BackgroundTransparency = 1,
FontSize = Enum.FontSize.Size18,
Position = UDim2.new(0.025,0,0,140),
Size = UDim2.new(0.4,0,0,36),
TextColor3 = Color3I(255,255,255),
TextXAlignment = Enum.TextXAlignment.Left,
},
Obj.Create"TextLabel"
{
Name = "ShortDescriptionLabel",
Text = "Short Description: (optional)",
Font = Enum.Font.Arial,
FontSize = Enum.FontSize.Size18,
Position = UDim2.new(0.025,0,0,180),
Size = UDim2.new(0.95,0,0,36),
TextColor3 = Color3I(255,255,255),
TextXAlignment = Enum.TextXAlignment.Left,
BackgroundTransparency = 1,
},
Obj.Create"TextLabel"
{
Name = "ReportingPlayerLabel",
Text = "Reporting Player",
BackgroundTransparency = 1,
Font = Enum.Font.Arial,
FontSize = Enum.FontSize.Size18,
Position = UDim2.new(0.025,0,0,100),
Size = UDim2.new(0.95,0,0,36),
TextColor3 = Color3I(255,255,255),
TextXAlignment = Enum.TextXAlignment.Left,
Parent = AbuseSettingsFrame
},
Parent = ReportAbuseFrame,
}
local AbusePlayerLabel = Obj.Create"TextLabel"
{
Name = "PlayerLabel",
Text = "",
BackgroundTransparency = 1,
Font = Enum.Font.ArialBold,
FontSize = Enum.FontSize.Size18,
Position = UDim2.new(0.025,0,0,100),
Size = UDim2.new(0.95,0,0,36),
TextColor3 = Color3I(255,255,255),
TextXAlignment = Enum.TextXAlignment.Right,
Parent = AbuseSettingsFrame
}
local SubmitReportButton = Obj.Create"ImageButton"
{
Name = "SubmitReportBtn",
Active = false,
BackgroundTransparency = 1,
Position = UDim2.new(.5, - 200, 1, - 80),
Size = UDim2.new(0,150,0,50),
AutoButtonColor = false,
Image = 'http://www.roblox.com/asset/?id=96502438', -- 96501119',
Parent = AbuseSettingsFrame,
}
local CancelReportButton = Obj.Create"ImageButton"
{
Name = "CancelBtn",
BackgroundTransparency = 1,
Position = UDim2.new(0.5, 50, 1, - 80),
Size = UDim2.new(0,150,0,50),
AutoButtonColor = true,
Image = 'http://www.roblox.com/asset/?id=96500683',
Parent = AbuseSettingsFrame,
}
local AbuseDescriptionWrapper = Obj.Create"Frame"
{
Name = "AbuseDescriptionWrapper",
Position = UDim2.new(0.025,0,0,220),
Size = UDim2.new(0.95,0,1, - 310),
BackgroundColor3 = Color3I(0,0,0),
BorderSizePixel = 0,
Parent = AbuseSettingsFrame,
}
local AbuseDescriptionBox
local OriginalAbuseDescriptionBox = Obj.Create"TextBox"
{
Name = "TextBox",
Text = "",
ClearTextOnFocus = false,
Font = Enum.Font.Arial,
FontSize = Enum.FontSize.Size18,
Position = UDim2.new(0,3,0,3),
Size = UDim2.new(1, - 6,1, - 6),
TextColor3 = Color3I(255,255,255),
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Top,
TextWrap = true,
BackgroundColor3 = Color3I(0,0,0),
BorderSizePixel = 0,
}
local CalmingAbuseBox = Obj.Create'Frame'
{
Name = 'AbuseFeedbackBox',
BackgroundTransparency = 1,
Position=UDim2.new(0.25, 0, 0.300000012, 0),
Size=UDim2.new(0.5, 0, 0.370000005, 0),
MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96506233'),
Obj.Create'TextLabel'
{
Name = 'Header',
Position=UDim2.new(0,10,.05,0),
Size=UDim2.new(1, -30, .15, 0),
TextScaled = true,
BackgroundTransparency = 1,
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Top,
Text = 'Thanks for your report!',
TextColor3 = Color3.new(1,1,1),
FontSize = Enum.FontSize.Size48,
Font = 'ArialBold',
},
Obj.Create'TextLabel'
{
Name = 'content',
Position = UDim2.new(0,10,.20,0),
Size = UDim2.new(1, -30, .40, 0),
TextScaled = true,
BackgroundTransparency = 1,
TextColor3 = Color3.new(1,1,1),
Text = 'Our moderators will review the chat logs and determine what happened. The other user is probably just trying to make you mad.\n\nIf anyone used swear words, inappropriate language, or threatened you in real life, please report them for Bad Words or Threats',
TextWrapped = true,
TextYAlignment = Enum.TextYAlignment.Top,
FontSize = Enum.FontSize.Size24,
Font = 'Arial',
},
Obj.Create'ImageButton'
{
Name = "OkButton",
BackgroundTransparency = 1,
Position = UDim2.new(0.5, -75, 1, -80),
Size = UDim2.new(0,150,0,50),
AutoButtonColor = true,
Image = 'http://www.roblox.com/asset/?id=96507959',
}
}
local NormalAbuseBox = Obj.Create'Frame'
{
Name = 'AbuseFeedbackBox',
BackgroundTransparency = 1,
Position = UDim2.new(0.25, 0, 0.300000012, 0),
Size = UDim2.new(0.5, 0, 0.370000005, 0),
MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96506233'),
Obj.Create'TextLabel'
{
Name = 'Header',
Position = UDim2.new(0,10,.05,0),
Size = UDim2.new(1, -30, .15, 0),
TextScaled = true,
BackgroundTransparency = 1,
TextColor3 = Color3.new(1,1,1),
TextXAlignment = Enum.TextXAlignment.Center,
TextYAlignment = Enum.TextYAlignment.Top,
Text = 'Thanks for your report!',
FontSize = Enum.FontSize.Size48,
Font ='ArialBold'
},
Obj.Create'TextLabel'
{
Name = 'content',
Position = UDim2.new(0,10,.20,0),
Size = UDim2.new(1, -30, .15, 0),
TextScaled = true,
BackgroundTransparency = 1,
TextColor3 = Color3.new(1,1,1),
Text = "Our moderators will review the chat logs and determine what happened.",
TextWrapped = true,
TextYAlignment = Enum.TextYAlignment.Top,
FontSize = Enum.FontSize.Size24,
Font = 'Arial',
},
Obj.Create'ImageButton'
{
Name = "OkButton",
BackgroundTransparency = 1,
Position = UDim2.new(0.5, -75, 1, -80),
Size = UDim2.new(0,150,0,50),
AutoButtonColor = true,
Image = 'http://www.roblox.com/asset/?id=96507959',
},
}
local BigButton=Instance.new('ImageButton')
BigButton.Size=UDim2.new(1,0,1,0)
BigButton.BackgroundTransparency=1
BigButton.ZIndex=8
BigButton.Visible=false
--BigButton.Active=false
BigButton.Parent=ScreenGui
local debugFrame = Obj.Create"Frame"
{
Name = 'debugframe',
Position = UDim2.new(0, 0, 0, 0),
Size = UDim2.new(0, 150, 0, 800),--0.99000001
BackgroundTransparency = 1,
}
local debugplayers = Obj.Create"TextLabel"
{
BackgroundTransparency = .8,
Position = UDim2.new(0, 0, .01, 0),
Size = UDim2.new(1,0,.5,0),
Parent = debugFrame,
Font = 'ArialBold',
Text = '--',
FontSize='Size14',
TextWrapped=true,
TextColor3 = Color3.new(1,1,1),
TextStrokeColor3 = Color3.new(0,0,0),
TextStrokeTransparency = 0,
TextXAlignment = 'Right',
TextYAlignment = 'Center',
}
local debugOutput = Obj.Create"TextLabel"
{
BackgroundTransparency = .8,
Position = UDim2.new(0, 0, .5, 0),
Size = UDim2.new(1,0,.5,0),
Parent = debugFrame,
Font = 'ArialBold',
Text = '--',
FontSize='Size14',
TextWrapped=true,
TextColor3 = Color3.new(1,1,1),
TextStrokeColor3 = Color3.new(0,0,0),
TextStrokeTransparency = 0,
TextXAlignment = 'Right',
TextYAlignment = 'Center',
}
--[[
simple function to toggle the display of debug output
--]]
local DebugPrintEnabled=true
function debugprint(str)
if DebugPrintEnabled then
debugOutput.Text=str
end
end
-------------------------
-- Script objects
-------------------------
local RbxGui = t
-- number of entries to show if you click minimize
local DefaultEntriesOnScreen = 8
local Images = {
bottomDark = '94691904',
bottomLight = '94691940',
midDark = '94691980',
midLight = '94692025',
LargeDark = '96098866',
LargeLight = '96098920',
LargeHeader = '96097470',
NormalHeader = '94692054',
LargeBottom = '96397271', -- '96098152',
NormalBottom = '94754966',
DarkBluePopupMid = '97114905',
LightBluePopupMid = '97114905',
DarkPopupMid = '97112126',
LightPopupMid = '97109338',
DarkBluePopupTop = '97114838',
LightBluePopupTop = '',
DarkPopupTop = '',
LightPopupTop = '',
DarkBluePopupBottom = '97114758',
LightBluePopupBottom = '',
DarkPopupBottom = '97109175',
LightPopupBottom = '',
}
for _,i in pairs(Images) do
Game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id="..i)
end
-- ordered array of 'score data', each entry has:
-- Name(String)
-- Priority(number)
-- IsPrimary (bool, should it be shown in upper right)
-- MaxLength (integer, of the length of the longest element for this column)
local ScoreNames = {}
-- prevents flipping in playerlist panels
local AddId = 0
-- intermediate table form of all player entries in format of:
-- Frame
-- Player
-- Score
-- ID
-- MyTeam (team ENRTY(not actual team) I am currently on)
local PlayerFrames = {}
-- intermediate ordered frame array, composed of Entrys of
-- Frame
-- MyTeam (my team object)
-- MyPlayers ( an ordered array of all player frames in team )
-- AutoHide (bool saying whether it should be hidden)
-- IsHidden (bool)
-- ID (int to prevent flipping out of leaderboard, fun times)
local TeamFrames = {}
-- one special entry from teamFrames, for unaffiliated players, only shown if players non - empty
local NeutralTeam = nil
-- final 'to be displayed' list of frames
local MiddleFrames = {}
local MiddleFrameBackgrounds = {}
local MiddleFrameHeight = .03
-- time of last click
local LastClick = 0
local ButtonCooldown = .25
local OnIos = false
pcall(function() OnIos = Game:GetService('UserInputService').TouchEnabled end)
-- you get 200 of x screen space per stat added, start width 16%
local BaseScreenXSize = 150
local SpacingPerStat = 10 --spacing between stats
local MaximizedBounds = UDim2.new(.5,0,1,0)
local MaximizedPosition = UDim2.new(.25,0,.1,0)
local NormalBounds = UDim2.new(0,BaseScreenXSize, 0, 800)
local NormalPosition = UDim2.new(1 , - BaseScreenXSize, 0.005, 0)
local MinimizedBounds = UDim2.new(0, BaseScreenXSize, 0.99000001, 0)
-- number of stats to show from leaderstats
local NumPrimaryStats = 0
-- where the scroll par currently is positioned
local ScrollPosition = 0.75999999
local IsDragging = false -- am I dragging the player list
local DefaultBottomClipPos = BottomClipFrame.Position.Y.Scale
local LastSelectedPlayerEntry = nil
local SelectedPlayerEntry = nil
local SelectedPlayer = nil
-- locks(semaphores) for stopping race conditions
local AddingFrameLock = false
local ChangingOrderLock = false
local AddingStatLock = false
local BaseUpdateLock = false
local WaitForClickLock = false
local InPopupWaitForClick=false
local PlayerChangedLock = false
local NeutralTeamLock = false
local ScrollWheelConnections = {}
-- report abuse objects
local AbuseName
local Abuses = {
"Bad Words or Threats",
"Bad Username",
"Talking about Dating",
"Account Trading or Sharing",
"Asking Personal Questions",
"Rude or Mean Behavior",
"False Reporting Me"
}
local UpdateAbuseFunction
local AbuseDropDown, UpdateAbuseSelection
local PrivilegeLevel =
{
Owner = 255,
Admin = 240,
Member = 128,
Visitor = 10,
Banned = 0,
}
local IsPersonalServer = not not game.Workspace:FindFirstChild("PSVariable")
if IsPersonalServer then
--THIS SHOULD NOT BE HERE GUYS, only keeping to perserve old functionality
game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager")
end
game.Workspace.ChildAdded:connect(function(nchild)
if nchild.Name=='PSVariable' and nchild:IsA('BoolValue') then
IsPersonalServer=true
--THIS SHOULD NOT BE HERE GUYS, only keeping to perserve old functionality
game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager")
end
end)
-------------------------------
-- Static Functions
-------------------------------
function GetTotalEntries()
return math.min(#MiddleFrameBackgrounds,DefaultEntriesOnScreen)
end
function GetEntryListLength()
local numEnts=#PlayerFrames+#TeamFrames
if NeutralTeam then
numEnts=numEnts+1
end
return numEnts
end
function AreAllEntriesOnScreen()
return #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale <= 1 + BottomClipFrame.Position.Y.Scale
end
function GetLengthOfVisbleScroll()
return 1 + BottomClipFrame.Position.Y.Scale
end
function GetMaxScroll()
return BottomClipFrame.Position.Y.Scale * - 1
end
-- can be optimized by caching when this varible changes
function GetMinScroll()
if AreAllEntriesOnScreen() then
return GetMaxScroll()
else
return (GetMaxScroll() - (#MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale)) + (1 + BottomClipFrame.Position.Y.Scale)
end
end
function AbsoluteToPercent(x,y)
return Vector2.new(x,y)/ScreenGui.AbsoluteSize
end
--[[
tweens text transparency of element from starta to enda over length of time
Warning: should be put in a Spawn call
@Args:
element textobject to tween transparency on
starta alpha to start tweening
enda alpha to end tweening on
length how many seconds to spend tweening
--]]
function TweenTextTransparency(element,starta,enda,length)
local startTime = time()
while time() - startTime < length do
element.TextTransparency = ((enda - starta) * ((time() - startTime)/length)) + starta
wait(.01)
end
element.TextTransparency = enda
end
--[[
tweens background transparency of element from starta to enda over length of time
Warning: should be put in a Spawn call
@Args:
element guiobject to tween transparency on
starta alpha to start tweening
enda alpha to end tweening on
length how many seconds to spend tweening
--]]
function TweenBackgroundTransparency(element,starta,enda,length)
local startTime = time()
while time() - startTime < length do
element.BackgroundTransparency = ((enda - starta) * ((time() - startTime)/length)) + starta
wait(.01)
end
element.BackgroundTransparency = enda
end
--[[
UGLY UGLY HACK FUNCTION
replace with some sort of global input catching A.S.A. FREAKING P.
creates a fullsize gui element to catch next mouse up event(completeing a click)
@Args:
frameParent Object to parent fullscreen gui to
polledFunction function to call on mouse moved events in this gui
exitFunction function to call when click event is fired
--]]
function WaitForClick(frameParent,polledFunction,exitFunction)
if WaitForClickLock then return end
debugprint('waiting for click!')
WaitForClickLock=true
BigButton.Visible=true
--BigButton.Active=true
--BigButton.Parent=frameParent
local upHappened=false
local connection, connection2
connection2=BigButton.MouseMoved:connect( function(nx,ny)
polledFunction(nx,ny)
end)
connection=BigButton.MouseButton1Up:connect(function(nx,ny)
exitFunction(nx,ny)
BigButton.Visible=false
connection:disconnect()
connection2:disconnect()
debugprint('mouse up!')
end)
frameParent.AncestryChanged:connect(function(child,nparent)
if child == frameParent and nparent ==nil then
exitFunction(nx,ny)
BigButton.Visible=false
connection:disconnect()
connection2:disconnect()
debugprint("forced out of wait for click")
end
end)
WaitForClickLock=false
end
---------------------------
--Personal Server Handling
---------------------------
--[[
returns privlage level based on integer rank
Note: these privilege levels seem completely arbitrary, but no documentation exists
this is all from the old player list, really weird
@Args:
rank Integer rank value for player
@Return Normalized integer value for rank?
--]]
function GetPrivilegeType(rank)
if rank <= PrivilegeLevel['Banned'] then
return PrivilegeLevel['Banned']
elseif rank <= PrivilegeLevel['Visitor'] then
return PrivilegeLevel['Visitor']
elseif rank <= PrivilegeLevel['Member'] then
return PrivilegeLevel['Member']
elseif rank <= PrivilegeLevel['Admin'] then
return PrivilegeLevel['Admin']
else
return PrivilegeLevel['Owner']
end
end
--[[
gives a player a new privilage rank
Note: Very odd that I have to use loops with this instead of directly setting the rank
but no documentation for personal server service exists
@Args:
player player to change rank of
nrank new integer rank to give player
--]]
function SetPrivilegeRank(player,nrank)
while player.PersonalServerRank<nrank do
game:GetService("PersonalServerService"):Promote(player)
end
while player.PersonalServerRank>nrank do
game:GetService("PersonalServerService"):Demote(player)
end
end
--[[
called when player selects new privilege level from popup menu
@Args:
player player to set privileges on
nlevel new privilege level for this player
--]]
function OnPrivilegeLevelSelect(player,nlevel)
debugprint('setting privilege level')
SetPrivilegeRank(player,nlevel)
HighlightMyRank(player)
PersonalServerPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true)
end
--[[
Highlights current rank of this player in the popup menu
@Args:
player Player to check for rank on
--]]
function HighlightMyRank(player)
BanPlayerButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid']
VisitorButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupMid']
MemberButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid']
AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupBottom']
local rank=player.PersonalServerRank
if rank <= PrivilegeLevel['Banned'] then
BanPlayerButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid']
elseif rank <= PrivilegeLevel['Visitor'] then
VisitorButton.Image='http://www.roblox.com/asset/?id='..Images['DarkBluePopupMid']
elseif rank <= PrivilegeLevel['Member'] then
MemberButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid']
elseif rank <= PrivilegeLevel['Admin'] then
AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkBluePopupBottom']
end
end
BanPlayerButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Banned']) end)
VisitorButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Visitor']) end)
MemberButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Member']) end)
AdminButton.MouseButton1Click:connect(function() BigButton.Visible=false OnPrivilegeLevelSelect(SelectedPlayer,PrivilegeLevel['Admin']) end)
--------------------------
-- Report abuse handling
--------------------------
--[[
does final reporting of abuse on selected player, calls closeAbuseDialog
--]]
function OnSubmitAbuse()
if SubmitReportButton.Active then
if AbuseName and SelectedPlayer then
AbuseSettingsFrame.Visible = false
game.Players:ReportAbuse(SelectedPlayer, AbuseName, AbuseDescriptionBox.Text)
if AbuseName == "Rude or Mean Behavior" or AbuseName == "False Reporting Me" then
CalmingAbuseBox.Parent = ReportAbuseShield
else
debugprint('opening abuse box')
NormalAbuseBox.Parent = ReportAbuseShield
end
else
CloseAbuseDialog()
end
end
end
--[[
opens the abuse dialog, initialises text to display selectedplayer
--]]
function OpenAbuseDialog()
debugprint('adding report dialog')
AbusePlayerLabel.Text = SelectedPlayer.Name
--AbuseDescriptionBox.Text = ""
PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true)
AbuseDescriptionBox=OriginalAbuseDescriptionBox:Clone()
AbuseDescriptionBox.Parent = AbuseDescriptionWrapper
ReportAbuseShield.Parent = ScreenGui
end
--[[
resets and closes abuse dialog
--]]
function CloseAbuseDialog()
AbuseName = nil
SubmitReportButton.Active = false
SubmitReportButton.Image = 'http://www.roblox.com/asset/?id=96502438' -- 96501119',
AbuseDescriptionBox:Destroy()
CalmingAbuseBox.Parent = nil
NormalAbuseBox.Parent = nil
ReportAbuseShield.Parent = nil
AbuseSettingsFrame.Visible = true
end
--[[
creates dropdownbox, registers all listeners for abuse dialog
--]]
function InitReportAbuse()
UpdateAbuseFunction = function(abuseText)
AbuseName = abuseText
if AbuseName and SelectedPlayer then
SubmitReportButton.Active = true
SubmitReportButton.Image = 'http://www.roblox.com/asset/?id=96501119'
end
end
AbuseDropDown, UpdateAbuseSelection = RbxGui.CreateDropDownMenu(Abuses, UpdateAbuseFunction, true)
AbuseDropDown.Name = "AbuseComboBox"
AbuseDropDown.Position = UDim2.new(0.425, 0, 0, 142)
AbuseDropDown.Size = UDim2.new(0.55,0,0,32)
AbuseDropDown.Parent = AbuseSettingsFrame
CancelReportButton.MouseButton1Click:connect(CloseAbuseDialog)
SubmitReportButton.MouseButton1Click:connect(OnSubmitAbuse)
ReportPlayerButton.MouseButton1Click:connect(function() BigButton.Visible=false OpenAbuseDialog() end)
PSReportPlayerButton.MouseButton1Click:connect(function() BigButton.Visible=false OpenAbuseDialog() end)
CalmingAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog)
NormalAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog)
end
-------------------------------------
-- Friend/unfriending
-------------------------------------
--[[
gets enum val of friend status, uses pcall for some reason?(from old playerlist)
@Args:
player player object to check if friends with
@Return: enum of friend status
--]]
local function GetFriendStatus(player)
if player == game.Players.LocalPlayer then
return Enum.FriendStatus.NotFriend
else
local success, result = pcall(function() return game.Players.LocalPlayer:GetFriendStatus(player) end)
if success then
return result
else
return Enum.FriendStatus.NotFriend
end
end
end
--[[
Updates text on popup friend button of SelectedPlayer
called when popup opens
--]]
function OnFriendPopUpOpen()
local friendButton
if IsPersonalServer and LocalPlayer.PersonalServerRank >= PrivilegeLevel['Admin'] then
friendButton=PSFriendPlayerButton
else
friendButton=FriendPlayerButton
end
local friendStatus=GetFriendStatus(SelectedPlayer)
debugprint('status: ' .. tostring(friendStatus))
if friendStatus==Enum.FriendStatus.Friend then
friendButton:FindFirstChild('ButtonText').Text='UnFriend Player'
elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then
friendButton:FindFirstChild('ButtonText').Text='Send Friend Request'
elseif friendStatus==Enum.FriendStatus.FriendRequestSent then
friendButton:FindFirstChild('ButtonText').Text='Revoke Friend Request'
elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then
friendButton:FindFirstChild('ButtonText').Text='Accept Friend Request'
end
end
--[[
when friend button is clicked, tries to take appropriate action,
based on current friend status with SelectedPlayer
--]]
function OnFriendButtonSelect()
BigButton.Visible=false
local friendStatus=GetFriendStatus(SelectedPlayer)
if friendStatus==Enum.FriendStatus.Friend then
LocalPlayer:RevokeFriendship(SelectedPlayer)
elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then
LocalPlayer:RequestFriendship(SelectedPlayer)
elseif friendStatus==Enum.FriendStatus.FriendRequestSent then
LocalPlayer:RevokeFriendship(SelectedPlayer)
elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then
LocalPlayer:RequestFriendship(SelectedPlayer)
end
PersonalServerPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true)
PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true)
end
PSFriendPlayerButton.MouseButton1Click:connect(OnFriendButtonSelect)
FriendPlayerButton.MouseButton1Click:connect(OnFriendButtonSelect)
------------------------------------
-- Player Entry Handling
------------------------------------
--[[
used by lua's table.sort to sort player entries
--]]
function PlayerSortFunction(a,b)
-- prevents flipping out leaderboard
if a['Score'] == b['Score'] then
return a['ID'] < b['ID']
end
if not a['Score'] then return false end
if not b['Score'] then return true end
return a['Score'] < b['Score']
end
---------------------------------
-- Stat Handling
---------------------------------
-- removes and closes all leaderboard stuffs
function BlowThisPopsicleStand()
--ScreenGui:Destroy()
--script:Destroy()
--time to make the fanboys rage...
Tabify()
end
--[[
used by lua's table.sort to prioritize score entries
--]]
function StatSort(a,b)
-- primary stats should be shown before all others
if a.IsPrimary ~= b.IsPrimary then
return a.IsPrimary
end
-- if priorities are equal, then return the first added one
if a.Priority == b.Priority then
return a.AddId < b.AddId
end
return a.Priority < b.Priority
end
--[[
doing WAAY too much here, for optimization update only your team
@Args:
playerEntry Entry of player who had a stat change
property Name of stat changed
--]]
function StatChanged(playerEntry,property)
-- if(playerEntry['MyTeam']) then
-- UpdateSingleTeam(playerEntry['MyTeam'])
-- else
BaseUpdate()
-- end
end
--[[
Called when stat is added
if playerEntry is localplayer, will add to score names and re-sort the stats, and resize the width of the leaderboard
for all players, will add a listener for if this stat changes
if stat is a string value, crashes the leaderboard
Note:change crash to a 'tabify' leaderboard later
@Args:
nchild new child value to leaderstats
playerEntry entry this stat was added to
--]]
function StatAdded(nchild,playerEntry)
-- dont re - add a leaderstat I alreday have
while AddingStatLock do debugprint('in stat added function lock') wait(1/30) end
AddingStatLock = true
if not (nchild:IsA('StringValue') or nchild:IsA('IntValue') or nchild:IsA('BoolValue') or nchild:IsA('NumberValue') or nchild:IsA('DoubleConstrainedValue') or nchild:IsA('IntConstrainedValue')) then
BlowThisPopsicleStand()
else
local haveScore = false
for _,i in pairs(ScoreNames) do
if i['Name']==nchild.Name then haveScore=true end
end
if not haveScore then
local nstat = {}
nstat['Name'] = nchild.Name
nstat['Priority'] = 0
if(nchild:FindFirstChild('Priority')) then
nstat['Priority'] = nchild.Priority
end
nstat['IsPrimary'] = false
if(nchild:FindFirstChild('IsPrimary')) then
nstat['IsPrimary'] = true
end
if(nstat['IsPrimary']) then
NumPrimaryStats = NumPrimaryStats + 1
end
nstat.AddId = AddId
AddId = AddId + 1
table.insert(ScoreNames,nstat)
table.sort(ScoreNames,StatSort)
UpdateMaximize()
end
end
AddingStatLock = false
StatChanged(playerEntry)
nchild.Changed:connect(function(property) StatChanged(playerEntry,property) end)
end
--[[
Called when stat is removed from player
for all players, destroys the stat frame associated with this value,
then calls statchanged(to resize frame)
if playerEntry==localplayer, will remove from scorenames
@Args:
nchild ___value to be removed
playerEntry entry of player value is being removed from
--]]
function StatRemoved(nchild,playerEntry)
while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end
AddingStatLock = true
if playerEntry['Frame']:FindFirstChild(nchild.Name) then
debugprint('Destroyed frame!')
playerEntry['Frame'][nchild.Name].Parent = nil
end
if playerEntry['Player'].Name == LocalPlayer.Name then
for i,val in ipairs(ScoreNames) do
if val['IsPrimary'] then
NumPrimaryStats = NumPrimaryStats - 1
end
if val['Name'] == nchild.Name then
table.remove(ScoreNames,i)
end
end
end
AddingStatLock = false
StatChanged(playerEntry)
end
--[[
clears all stats from a given playerEntry
used when leaderstats are removed, or when new leaderstats are added(for weird edge case)+
--]]
function RemoveAllStats(playerEntry)
while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end
AddingStatLock = true
for i,val in ipairs(ScoreNames) do
if playerEntry['Frame']:FindFirstChild(val['Name']) then
debugprint('Destroyed frame!')
playerEntry['Frame'][val['Name']].Parent = nil
end
if playerEntry['Player'].Name == LocalPlayer.Name then
NumPrimaryStats = NumPrimaryStats - 1
end
end
if playerEntry['Player'].Name == LocalPlayer.Name then
NumPrimaryStats = NumPrimaryStats - 1
end
AddingStatLock = false
StatChanged(playerEntry)
end
function GetScoreValue(score)
if score:IsA('DoubleConstrainedValue') or score:IsA('IntConstrainedValue') then
return score.ConstrainedValue
elseif score:IsA('BoolValue') then
if score.Value then return 1 else return 0 end
else
return score.Value
end
end
--[[
--]]
function MakeScoreEntry(entry,scoreval,panel)
if not panel:FindFirstChild('PlayerScore') then return end
local nscoretxt = panel:FindFirstChild('PlayerScore'):Clone()
local thisScore = nil
--here lies the resting place of a once great and terrible bug
--may its treachery never be forgoten, lest its survivors fall for it again
--RIP the leaderstat bug, oct 2012-nov 2012
wait()
if entry['Player']:FindFirstChild('leaderstats') then
thisScore = entry['Player']:FindFirstChild('leaderstats'):FindFirstChild(scoreval['Name'])
else
return
end
if not entry['Player'].Parent then return end
nscoretxt.Name = scoreval['Name']
nscoretxt.Text = tostring(GetScoreValue(thisScore))
if scoreval['Name'] == ScoreNames[1]['Name'] then
debugprint('changing score')
entry['Score'] = GetScoreValue(thisScore)
if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end
end
thisScore.Changed:connect(function()
if not thisScore.Parent then return end
if scoreval['Name'] == ScoreNames[1]['Name'] then
entry['Score'] = GetScoreValue(thisScore)
if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end
end
nscoretxt.Text = tostring(GetScoreValue(thisScore))
BaseUpdate()
end)
return nscoretxt
end
function CreateStatTitle(statName)
local ntitle = MiddleTemplate:FindFirstChild('PlayerScore'):Clone()
ntitle.Name = statName
ntitle.Text = statName
-- ntitle
if IsMaximized.Value then
ntitle.TextTransparency = 0
else
ntitle.TextTransparency = 1
end
ntitle.Parent = StatTitles
end
function RecreateScoreColumns(ptable)
while AddingStatLock do debugprint ('In Adding Stat Lock2') wait(1/30) end
AddingStatLock = true
local Xoffset=BaseScreenXSize --current offset from left
local maxXOffset=Xoffset
local MaxSizeColumn=0 --max size for this column
-- foreach known leaderstat
for j = 1, #ScoreNames,1 do
local scoreval = ScoreNames[j]
--if scoreval['ColumnSize'] then
-- MaxSizeColumn=0--scoreval['ColumnSize']
--else
MaxSizeColumn=0
--end
-- for each entry in this player table
for i,entry in ipairs(ptable) do
local panel = entry['Frame']
local tplayer = entry['Player']
-- if this panel does not have an element named after this stat
if not panel:FindFirstChild(scoreval['Name']) then
-- make an entry for this object
local nentry = MakeScoreEntry(entry,scoreval,panel)
if nentry then
debugprint('adding '..nentry.Name..' to '..entry['Player'].Name )
nentry.Parent = panel
-- add score to team
if entry['MyTeam'] and entry['MyTeam'] ~= NeutralTeam and not entry['MyTeam']['Frame']:FindFirstChild(scoreval['Name']) then
local ntitle = nentry:Clone()
ntitle.Parent = entry['MyTeam']['Frame']
end
end
end
scoreval['XOffset']=Xoffset
if panel:FindFirstChild(scoreval['Name']) then
MaxSizeColumn=math.max(MaxSizeColumn,panel[scoreval['Name']].TextBounds.X)
end
end
-- add stat title to top bar
if not StatTitles:FindFirstChild(scoreval['Name']) then
CreateStatTitle(scoreval['Name'])
end
if AreNamesExpanded.Value then
MaxSizeColumn=math.max(MaxSizeColumn,StatTitles[scoreval['Name'] ].TextBounds.X)
StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(0,Xoffset,0,0),'Out','Quad',.25,true)
else
StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0),'Out','Quad',.25,true)
end
scoreval['ColumnSize']=MaxSizeColumn
Xoffset= Xoffset+SpacingPerStat+MaxSizeColumn
maxXOffset=math.max(Xoffset,maxXOffset)
end
--print(maxXOffset)
NormalBounds = UDim2.new(0, maxXOffset,0,800)
NormalPosition = UDim2.new(1 , -NormalBounds.X.Offset, NormalPosition.Y.Scale, 0)
UpdateHeaderNameSize()
UpdateMaximize()
AddingStatLock = false
end
---------------------------
-- Minimizing and maximizing
---------------------------
function ToggleMinimize()
IsMinimized.Value = not IsMinimized.Value
end
function ToggleMaximize()
IsMaximized.Value = not IsMaximized.Value
end
function Tabify()
IsTabified.Value= true
IsMaximized.Value=false
IsMinimized.Value=true
UpdateMinimize()
IsTabified.Value= true
ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Quad',1,true)
end
function UnTabify()
if IsTabified.Value then
IsTabified.Value= false
ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Quad',1,true)
end
end
--[[
Does more than it looks like
monitors positions of the clipping frames and bottom frames
called from EVERYWHERE
--]]
function UpdateMinimize()
if IsMinimized.Value then
if IsMaximized.Value then
ToggleMaximize()
end
if not IsTabified.Value then
MainFrame:TweenSizeAndPosition(UDim2.new(0.010, HeaderName.TextBounds.X, NormalBounds.Y.Scale,NormalBounds.Y.Offset),
UDim2.new(.990, -HeaderName.TextBounds.X, NormalPosition.Y.Scale,0),'Out','Quad',1,true)
else
MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true)
end
BottomClipFrame:TweenPosition(UDim2.new(0,0,DefaultBottomClipPos - (((GetTotalEntries()) * MiddleTemplate.Size.Y.Scale)),0), "Out", "Linear", .25,true)
BottomFrame:TweenPosition(UDim2.new(0,0,0,0), "Out", "Linear", .25,true)
FocusFrame.Size=UDim2.new(1,0,HeaderFrameHeight,0)
ExtendTab.Image = 'http://www.roblox.com/asset/?id=94692731'
else
if not IsMaximized.Value then
MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true)
end
BottomClipFrame:TweenPosition(UDim2.new(0,0,DefaultBottomClipPos,0), "Out", "Linear", .25,true)
BottomFrame:TweenPosition(UDim2.new(0,0,((GetTotalEntries()) * MiddleTemplate.Size.Y.Scale),0), "Out", "Linear", .25,true)
FocusFrame.Size=UDim2.new(1,0,((GetTotalEntries()) * MiddleTemplate.Size.Y.Scale) + HeaderFrameHeight,0)
ExtendTab.Image = 'http://www.roblox.com/asset/?id=94825585'
end
end
--[[
Manages the position/size of the mainFrame, swaps out different resolution images for the frame
fades in and out the stat names, moves position of headername and header score
--]]
function UpdateMaximize()
if IsMaximized.Value then
--undo any 'name showing', without invoking base update
if AreNamesExpanded.Value then
CloseNames()
for j = 1, #ScoreNames,1 do
local scoreval = ScoreNames[j]
StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0),'Out','Quad',.25,true)
end
end
if IsMinimized.Value then
ToggleMinimize()
else
UpdateMinimize()
end
MainFrame:TweenSizeAndPosition(MaximizedBounds,MaximizedPosition,'Out','Quad',1,true)
HeaderScore:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true)
HeaderName:TweenPosition(UDim2.new( - .1, - HeaderScore.TextBounds.x,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true)
HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeHeader']
BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeBottom']
for index, i in ipairs(MiddleFrameBackgrounds) do
if (index%2) ~= 1 then
i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeDark']
else
i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeLight']
end
end
for index, i in ipairs(MiddleFrames) do
if i:FindFirstChild('ClickListener') then
i.ClickListener.Size = UDim2.new(.974,0,i.ClickListener.Size.Y.Scale,0)
end
for j=1, #ScoreNames,1 do
local scoreval = ScoreNames[j]
if i:FindFirstChild(scoreval['Name']) then
i[scoreval['Name']]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0), "Out", "Linear", .25,true)
end
end
end
for i,entry in ipairs(PlayerFrames) do
WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0)
end
for i,entry in ipairs(TeamFrames) do
WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0)
end
else
if not IsMinimized.Value then
MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true)
end
HeaderScore:TweenPosition(UDim2.new(0,0,.4,0), "Out", "Linear", .25,true)
HeaderName:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true)
HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalHeader']
BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalBottom']
for index, i in ipairs(MiddleFrameBackgrounds) do
if index%2 ~= 1 then
i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midDark']
else
i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midLight']
end
end
for index, i in ipairs(MiddleFrames) do
if i:FindFirstChild('ClickListener') then
i.ClickListener.Size = UDim2.new(.96,0,i.ClickListener.Size.Y.Scale,0)
for j=1, #ScoreNames,1 do
local scoreval = ScoreNames[j]
--print(scoreval['XOffset'])
if i:FindFirstChild(scoreval['Name']) and scoreval['XOffset'] then
--print('updateing stat position: ' .. scoreval['Name'])
i[scoreval['Name']]:TweenPosition(UDim2.new(0,scoreval['XOffset'],0,0), "Out", "Linear", .25,true)
end
end
end
end
if not AreNamesExpanded.Value then
for _,i in pairs(StatTitles:GetChildren()) do
Spawn(function()TweenTextTransparency(i,i.TextTransparency,1,.25) end)
end
end
for i,entry in ipairs(TeamFrames) do
WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0)
end
for i,entry in ipairs(PlayerFrames) do
WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0)
end
end
end
function ExpandNames()
if #ScoreNames ~= 0 then
for _,i in pairs(StatTitles:GetChildren()) do
Spawn(function()TweenTextTransparency(i,i.TextTransparency,0,.25) end)
end
HeaderFrameHeight=.09
--as of writing, this and 'CloseNames' are the only places headerframe is resized
HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0),
HeaderFrame.Position,'Out','Quad',.25,true)
TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Quad',.25,true)
BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Quad', .25,true)
AreNamesExpanded.Value=true
end
end
function CloseNames()
if #ScoreNames ~= 0 then
HeaderFrameHeight=.07
if not (IsMaximized.Value) then
for _,i in pairs(StatTitles:GetChildren()) do
Spawn(function()TweenTextTransparency(i,i.TextTransparency,1,.25) end)
end
end
BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Quad', .25,true)
HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0),
HeaderFrame.Position,'Out','Quad',.25,true)
TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Quad',.25,true)
AreNamesExpanded.Value=false
end
end
function OnScrollWheelMove(direction)
if not (IsTabified.Value or IsMinimized.Value) then
local StartFrame = ListFrame.Position
local newFrameY = math.max(math.min(StartFrame.Y.Scale + (direction),GetMaxScroll()),GetMinScroll())
ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset)
UpdateScrollPosition()
end
end
function AttachScrollWheel()
if ScrollWheelConnections then return end
local pmouse = LocalPlayer:GetMouse()
ScrollWheelConnections = {}
table.insert(ScrollWheelConnections,pmouse.WheelForward:connect(function()
OnScrollWheelMove(.05)
end))
table.insert(ScrollWheelConnections,pmouse.WheelBackward:connect(function()
OnScrollWheelMove(-.05)
end))
end
function DetachScrollWheel()
if ScrollWheelConnections then
for _,i in pairs(ScrollWheelConnections) do
i:disconnect()
end
end
ScrollWheelConnections=nil
end
FocusFrame.MouseEnter:connect(function()
if not (IsMaximized.Value or IsMinimized.Value or IsTabified.Value) then
ExpandNames()
AttachScrollWheel()
BaseUpdate()
if IsTabified.Value then
Tabify()
end
end
end)
FocusFrame.MouseLeave:connect(function()
--if not (IsMaximized.Value or IsMinimized.Value) then
CloseNames()
DetachScrollWheel()
BaseUpdate()
if IsTabified.Value then
Tabify()
end
--end
end)
------------------------
-- Scroll Bar functions
------------------------
--[[
updates whether the scroll bar should be showing, if it is showing, updates
the size of it
--]]
function UpdateScrollBarVisibility()
if AreAllEntriesOnScreen() then
ScrollBar.BackgroundTransparency = 1
else
ScrollBar.BackgroundTransparency = 0
UpdateScrollBarSize()
end
end
--[[
updates size of scrollbar depending on how many entries exist
--]]
function UpdateScrollBarSize()
local entryListSize = #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale
local shownAreaSize = ((BottomClipFrame.Position.Y.Scale) + 1)
ScrollBar.Size = UDim2.new(1,0,shownAreaSize/entryListSize,0)
end
--[[
updates position of listframe so that no gaps at the bottom or top of the list are visible
updates position of scrollbar to match what parts of the list are visible
--]]
function UpdateScrollPosition()
local minPos = GetMinScroll()
local maxPos = GetMaxScroll()
local scrollLength = maxPos - minPos
local yscrollpos=math.max(math.min(ListFrame.Position.Y.Scale,maxPos),minPos)
ListFrame.Position=UDim2.new(ListFrame.Position.X.Scale,ListFrame.Position.X.Offset,yscrollpos,ListFrame.Position.Y.Offset)
local adjustedLength = 1 - ScrollBar.Size.Y.Scale
ScrollBar.Position = UDim2.new(0,0,adjustedLength - (adjustedLength * ((ListFrame.Position.Y.Scale - minPos)/scrollLength)),0)
end
--[[
WARNING:this is in a working state, but uses massive hacks
revize when global input is available
Manages scrolling of the playerlist on mouse drag
--]]
function StartDrag()
Delay(0,function()
debugprint('Got Click')
local stopDrag = false
local function dragExit()
debugprint('undone click')
stopDrag = true
end
local startY = nil --AbsoluteToPercent(Mouse.X,Mouse.Y).Y
local StartFrame = ListFrame.Position
local function dragpoll(nx,ny)
if not startY then
startY = AbsoluteToPercent(nx,ny).Y
end
local nowY = AbsoluteToPercent(nx,ny).Y
local newFrameY
if OnIos then
newFrameY = math.max(math.min(StartFrame.Y.Scale + (nowY - startY),GetMaxScroll()),GetMinScroll())
else
newFrameY = math.max(math.min(StartFrame.Y.Scale - (nowY - startY),GetMaxScroll()),GetMinScroll())
end
ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset)
UpdateScrollPosition()
end
Spawn(function() WaitForClick(ScreenGui,dragpoll,dragExit) end)
end)
end
-------------------------------
-- Input Callback functions
-------------------------------
IsMaximized.Value=false
IsMinimized.Value=false
IsMaximized.Changed:connect(UpdateMaximize)
IsMinimized.Changed:connect(UpdateMinimize)
ExtendButton.MouseButton1Click:connect(function()
if(time() - LastClick < ButtonCooldown) then return end
LastClick = time()
UnTabify()
ToggleMinimize()
end)
MaximizeButton.MouseButton1Click:connect(function()
if(time() - LastClick < ButtonCooldown) then return end
LastClick = time()
if IsTabified.Value then
UnTabify()
else
ToggleMaximize()
end
end)
MaximizeButton.MouseButton2Click:connect(function()
if(time() - LastClick < ButtonCooldown) then return end
LastClick = time()
if IsTabified.Value then
UnTabify()
else
Tabify()
end
end)
-------------------------------
-- MiddleFrames management
-------------------------------
--[[
adds a background frame to the listframe
--]]
function AddMiddleBGFrame()
local nBGFrame = MiddleBGTemplate:Clone()
nBGFrame.Position = UDim2.new(.5,0,((#MiddleFrameBackgrounds) * nBGFrame.Size.Y.Scale),0)
if (#MiddleFrameBackgrounds+1)%2 ~= 1 then
if IsMaximized.Value then
nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeDark']
else
nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midDark']
end
else
if IsMaximized.Value then
nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeLight']
else
nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midLight']
end
end
nBGFrame.Parent = ListFrame
table.insert(MiddleFrameBackgrounds,nBGFrame)
if not IsMinimized.Value then
-- BottomFrame:TweenPosition(UDim2.new(0,0,((#MiddleFrameBackgrounds) * nBGFrame.Size.Y.Scale) + HeaderFrameHeight,0), "Out", "Quad", .5,true)
UpdateMinimize()
end
end
--[[
removes a background from from the listframe
--]]
function RemoveMiddleBGFrame()
MiddleFrameBackgrounds[#MiddleFrameBackgrounds]:Destroy()
table.remove(MiddleFrameBackgrounds,#MiddleFrameBackgrounds)
if not IsMinimized.Value then
-- BottomFrame:TweenPosition(UDim2.new(0,0,((#MiddleFrameBackgrounds) * MiddleTemplate.Size.Y.Scale) + HeaderFrameHeight,0), "Out", "Quad", .5)
UpdateMinimize()
end
end
-------------------------------
-- Player Callback functions
-------------------------------
local FONT_SIZES =
{'Size8','Size9','Size10','Size11','Size12','Size14','Size24','Size36','Size48'}
--[[
note:should probably set to something other than mainFrame.AbsoluteSize, should work for now
if textbounds ever works on textscaled, switch to that :(
--]]
function ChangeHeaderName(nname)
HeaderName.Text = nname
UpdateHeaderNameSize()
end
--[[
Will fit the player's name to the bounds of the header
called on resize of the window and playedr name change events
HACK: cannot use 'Textscaled' due to unable to find text bounds when scaled
--]]
function UpdateHeaderNameSize()
local tHeader= HeaderName:Clone()
tHeader.Position=UDim2.new(2,0,2,0)
tHeader.Parent=ScreenGui
local fSize=7 --Size24 in table
tHeader.FontSize=FONT_SIZES[fSize]
Delay(.2,function()
while tHeader.TextBounds.x==0 do wait(1/30) end
while tHeader.TextBounds.x-(NormalBounds.X.Offset) > 1 do
fSize=fSize-1
tHeader.FontSize=FONT_SIZES[fSize]
wait(.2)
end
HeaderName.FontSize=tHeader.FontSize
tHeader:Destroy()
end)
end
ScreenGui.Changed:connect(UpdateHeaderNameSize)
--[[
called only when the leaderstats object is added to a given player entry
removes old stats, adds any existing stats, and sets up listeners for new stats
@Args:
playerEntry A reference to the ENTRY(table) of the player who had leaderstats added
--]]
function LeaderstatsAdded(playerEntry)
--RemoveAllStats(playerEntry)
local nplayer = playerEntry['Player']
for _,i in pairs(nplayer.leaderstats:GetChildren()) do
StatAdded(i,playerEntry)
end
nplayer.leaderstats.ChildAdded:connect(function(nchild) StatAdded(nchild,playerEntry) end)
nplayer.leaderstats.ChildRemoved:connect(function(nchild) StatRemoved(nchild,playerEntry) end)
end
--[[
called when leaderstats object is removed from play in player entry
Note: may not be needed, might be able to just rely on leaderstats added
@Args:
oldLeaderstats leaderstats object to be removed
playerEntry A reference to the ENTRY(table) of the player
--]]
function LeaderstatsRemoved(oldLeaderstats,playerEntry)
while AddingFrameLock do debugprint('waiting to insert '..playerEntry['Player'].Name) wait(1/30) end
AddingFrameLock = true
RemoveAllStats(playerEntry)
AddingFrameLock = false
end
--[[
prepares the needed movingpanel to be tweened on screen, and updates the position of the popup clip
frame to match the selected player frame's position
@Args:
movingPanel The popup panel to tween on screen
--]]
function InitMovingPanel(movingPanel)
PopUpClipFrame.Parent= SelectedPlayerEntry['Frame']
PopUpClipFrame.Position = UDim2.new( 0,-PopUpClipFrame.Size.X.Offset,0,0)
movingPanel:TweenPosition(UDim2.new(0,0,0,0), "Out", "Quad", .5,true)
OnFriendPopUpOpen()
if IsPersonalServer then
HighlightMyRank(SelectedPlayer)
end
WaitForClick(ScreenGui,function() end,function(nx,ny)
movingPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true)
--connection:disconnect()
end)
end
--[[
Called when a player entry in the leaderboard is clicked
either will highlight entry and start the drag event, or open a popup menu
@Args:
entry the player entry clicked
--]]
function OnPlayerEntrySelect(entry)
local movingPanel
--if this is a personal server, and you are an admin and the selected person is a lower rank than you, then...
if IsPersonalServer and LocalPlayer.PersonalServerRank >= PrivilegeLevel['Admin'] and LocalPlayer.PersonalServerRank > SelectedPlayer.PersonalServerRank then
--and LocalPlayer.PersonalServerRank>entry['Player'].PersonalServerRank then
movingPanel=PersonalServerPanel
else
movingPanel=PopUpPanel
end
if entry == SelectedPlayerEntry and SelectedPlayer~=LocalPlayer and SelectedPlayer.userId>1 and LocalPlayer.userId>1 then
InPopupWaitForClick=true
WaitForClick(ScreenGui,function() end, function()
InitMovingPanel(movingPanel)
SelectedPlayerEntry = nil
inWaitForClick=false
end)
else
--movingPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true)
SelectedPlayerEntry = entry
SelectedPlayer = entry['Player']
entry['Frame'].BackgroundColor3 = Color3.new(0,1,1)
entry['Frame'].BackgroundTransparency = .5
Spawn(function() TweenBackgroundTransparency(entry['Frame'],.5,1,1) end)
Delay(1, function()
if not InPopupWaitForClick then
SelectedPlayerEntry = nil
end
end)
StartDrag()
end
end
--[[
the basic update for the playerlist mode's state,
assures the order and length of the player frames
--]]
function PlayerListModeUpdate()
RecreateScoreColumns(PlayerFrames)
table.sort(PlayerFrames,PlayerSortFunction)
for i,val in ipairs(PlayerFrames) do
MiddleFrames[i] = val['Frame']
end
for i = #PlayerFrames + 1,#MiddleFrames,1 do
MiddleFrames[i] = nil
end
UpdateMinimize()
end
--[[
this one's a doozie, happens when a player is added to the game
inits their player frame and player entry, assigns them to a team if possible,
and hooks up their leaderstats
@Args:
nplayer new player object to insert
--]]
function InsertPlayerFrame(nplayer)
while AddingFrameLock do debugprint('waiting to insert '..nplayer.Name) wait(1/30) end
AddingFrameLock = true
local nFrame = MiddleTemplate:Clone()
WaitForChild(WaitForChild(nFrame,'TitleFrame'),'Title').Text = nplayer.Name
nFrame.Position = UDim2.new(1,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0)
local nfriendstatus = GetFriendStatus(nplayer)
nFrame:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(nplayer.MembershipType,nplayer.Name)
nFrame:FindFirstChild('FriendLabel').Image = getFriendStatusIcon(nfriendstatus)
nFrame.Name = nplayer.Name
WaitForChild(WaitForChild(nFrame,'TitleFrame'),'Title').Text = nplayer.Name
--move for bc label
nFrame.FriendLabel.Position=nFrame.FriendLabel.Position+UDim2.new(0,17,0,0)
nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,17,0,0)
if(nFrame:FindFirstChild('FriendLabel').Image ~= '') then
nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,17,0,0)
--nFrame.FriendLabel.Position=nFrame.TitleFrame.Position+UDim2.new(nFrame.TitleFrame.Size.X.Scale,-20+nFrame.TitleFrame.Size.X.Offset,0,0)
end
if nplayer.Name == LocalPlayer.Name then
nFrame.TitleFrame.Title.Font = 'ArialBold'
nFrame.PlayerScore.Font = 'ArialBold'
ChangeHeaderName(nplayer.Name)
local dropShadow = nFrame.TitleFrame.Title:Clone()
dropShadow.TextColor3 = Color3.new(0,0,0)
dropShadow.TextTransparency=0
dropShadow.ZIndex=2
dropShadow.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,1,0,1)
dropShadow.Name='DropShadow'
dropShadow.Parent= nFrame.TitleFrame
elseif LocalPlayer:IsFriendsWith(nplayer.userId) then
end
nFrame.TitleFrame.Title.Font = 'ArialBold'
nFrame.Parent = ListFrame
nFrame:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0), "Out", "Quad", .5,true)
UpdateMinimize()
local nentry = {}
nentry['Frame'] = nFrame
nentry['Player'] = nplayer
nentry['ID'] = AddId
AddId = AddId + 1
table.insert(PlayerFrames,nentry)
if #TeamFrames~=0 then
if nplayer.Neutral then
nentry['MyTeam'] = nil
if not NeutralTeam then
AddNeutralTeam()
else
AddPlayerToTeam(NeutralTeam,nentry)
end
else
local addedToTeam=false
for i,tval in ipairs(TeamFrames) do
if tval['MyTeam'].TeamColor == nplayer.TeamColor then
AddPlayerToTeam(tval,nentry)
nentry['MyTeam'] = tval
addedToTeam=true
end
end
if not addedToTeam then
nentry['MyTeam']=nil
if not NeutralTeam then
AddNeutralTeam()
else
AddPlayerToTeam(NeutralTeam,nentry)
end
nentry['MyTeam'] = NeutralTeam
end
end
end
if nplayer==LocalPlayer and nplayer:FindFirstChild('leaderstats') then
LeaderstatsAdded(nentry)
end
nplayer.ChildAdded:connect(function(nchild)
if nplayer==LocalPlayer and nchild.Name == 'leaderstats' then
while AddingFrameLock do debugprint('in adding leaderstats lock') wait(1/30) end
AddingFrameLock = true
LeaderstatsAdded(nentry)
AddingFrameLock = false
end
end)
nplayer.ChildRemoved:connect(function (nchild)
if nplayer==LocalPlayer and nchild.Name == 'leaderstats' then
LeaderstatsRemoved(nchild,nentry)
end
end)
nplayer.Changed:connect(function(prop)PlayerChanged(nentry,prop) end)
local listener = WaitForChild(nFrame,'ClickListener')
listener.Active = true
listener.MouseButton1Down:connect(function() OnPlayerEntrySelect(nentry) end)
AddMiddleBGFrame()
BaseUpdate()
AddingFrameLock = false
end
--[[
Note:major optimization can be done here
removes this player's frame if it exists, calls base update
--]]
function RemovePlayerFrame(tplayer)
while AddingFrameLock do debugprint('in removing player frame lock') wait(1/30) end
AddingFrameLock = true
local tteam
for i,key in ipairs(PlayerFrames) do
if tplayer == key['Player'] then
if PopUpClipFrame.Parent == key['Frame'] then
PopUpClipFrame.Parent = nil
end
key['Frame']:Destroy()
tteam=key['MyTeam']
table.remove(PlayerFrames,i)
end
end
if tteam then
for j,tentry in ipairs(tteam['MyPlayers']) do
if tentry['Player'] == tplayer then
RemovePlayerFromTeam(tteam,j)
end
end
end
RemoveMiddleBGFrame()
UpdateMinimize()
BaseUpdate()
AddingFrameLock = false
end
Players.ChildRemoved:connect(RemovePlayerFrame)
----------------------------
-- Team Callback Functions
----------------------------
--[[
turns a list of team entries with sub lists of players into a single ordered
list, in the correct order,and of the correct length
@Args:
tframes the team entries to unroll
outframes the list to unroll these entries into
--]]
function UnrollTeams(tframes,outframes)
local numEntries = 0
if NeutralTeam and not NeutralTeam['IsHidden'] then
for i,val in ipairs(NeutralTeam['MyPlayers']) do
numEntries = numEntries + 1
outframes[numEntries] = val['Frame']
end
numEntries = numEntries + 1
outframes[numEntries] = NeutralTeam['Frame']
end
for i,val in ipairs(tframes) do
if not val['IsHidden'] then
for j,pval in ipairs(val.MyPlayers) do
numEntries = numEntries + 1
outframes[numEntries] = pval['Frame']
end
numEntries = numEntries + 1
outframes[numEntries] = val['Frame']
end
end
-- clear any additional entries from outframes
for i = numEntries + 1,#outframes,1 do
outframes[i] = nil
end
end
--[[
uses lua's table.sort to sort the teams
--]]
function TeamSortFunc(a,b)
if a['TeamScore'] == b['TeamScore'] then
return a['ID'] < b['ID']
end
if not a['TeamScore'] then return false end
if not b['TeamScore'] then return true end
return a['TeamScore'] < b['TeamScore']
end
--[[
consider adding lock with wait for performance
sorts each of the team's player lists induvidually, adds up the team scores.
@Args:
tentries table of team entries
--]]
function SortTeams(tentries)
for i,val in ipairs(tentries) do
table.sort(val['MyPlayers'],PlayerSortFunction)
AddTeamScores(val)
end
table.sort(tentries,TeamSortFunc)
end
--[[
base update for team mode, adds up the scores of all teams, sorts them,
then unrolls them into middleframes
--]]
function TeamListModeUpdate()
RecreateScoreColumns(PlayerFrames)
SortTeams(TeamFrames)
if NeutralTeam then
AddTeamScores(NeutralTeam)
--RecreateScoreColumns(NeutralTeam['MyPlayers'])
end
UnrollTeams(TeamFrames,MiddleFrames)
end
--[[
adds up all the score of this team's players to form the team score
@Args:
team team entry to sum the scores of
--]]
function AddTeamScores(team)
for j = 1, #ScoreNames,1 do
local i = ScoreNames[j]
local tscore = 0
for _,j in ipairs(team['MyPlayers']) do
if j['Player']:FindFirstChild('leaderstats') and j['Player'].leaderstats:FindFirstChild(i['Name']) then
tscore = tscore + GetScoreValue(j['Player'].leaderstats[i['Name']])
end
end
if team['Frame']:FindFirstChild(i['Name']) then
team['Frame'][i['Name']].Size = UDim2.new(1 - (ScrollBarFrame.Size.X.Scale * 2),- ((j-1) * SpacingPerStat),TemplateFrameYSize,0)
team['Frame'][i['Name']].Text = tostring(tscore)
end
end
UpdateMinimize()
end
--[[
finds previous team this player was on, and if it exists calls removeplayerfromteam
@Args
entry Player entry
--]]
function FindRemovePlayerFromTeam(entry)
if entry['MyTeam'] then
for j,oldEntry in ipairs(entry['MyTeam']['MyPlayers']) do
if oldEntry['Player'] == entry['Player'] then
RemovePlayerFromTeam(entry['MyTeam'],j)
return
end
end
elseif NeutralTeam then
for j,oldEntry in ipairs(NeutralTeam['MyPlayers']) do
if oldEntry['Player'] == entry['Player'] then
RemovePlayerFromTeam(NeutralTeam,j)
return
end
end
end
end
--[[
removes a single player from a given team (not usually called directly)
@Args:
teamEntry team entry to remove player from
index index of player in 'MyPlayers' list to remove
--]]
function RemovePlayerFromTeam(teamEntry,index)
table.remove(teamEntry['MyPlayers'],index)
--if teamEntry['AutoHide'] and #teamEntry['MyPlayers'] == 0 then
if teamEntry==NeutralTeam and #teamEntry['MyPlayers']==0 then
RemoveNeutralTeam()
end
end
--[[
adds player entry entry to teamentry
removes them from any previous team
@Args:
teamEntry entry of team to add player to
entry player entry to add to this team
--]]
function AddPlayerToTeam(teamEntry,entry)
FindRemovePlayerFromTeam(entry)
table.insert(teamEntry['MyPlayers'],entry)
entry['MyTeam'] = teamEntry
if teamEntry['IsHidden'] then
teamEntry['Frame'].Parent = ListFrame
AddMiddleBGFrame()
end
teamEntry['IsHidden'] = false
end
function SetPlayerToTeam(entry)
FindRemovePlayerFromTeam(entry)
-- check to see if team exists, if it does add to that team
local setToTeam = false
for i,tframe in ipairs(TeamFrames) do
-- add my entry on the new team
if tframe['MyTeam'].TeamColor == entry['Player'].TeamColor then
AddPlayerToTeam(tframe,entry)
setToTeam = true
end
end
-- if player was set to an invalid team, then set it back to neutral
if not setToTeam then
entry['MyTeam']=nil
if not NeutralTeam then
AddNeutralTeam()
else AddPlayerToTeam(NeutralTeam,entry) end
end
end
--[[
Note:another big one, consiter breaking up
called when any children of player changes
handles 'Neutral', teamColor, Name and MembershipType changes
@Args
entry Player entry changed
property name of property changed
--]]
function PlayerChanged(entry, property)
while PlayerChangedLock do
debugprint('in playerchanged lock')
wait(1/30)
end
PlayerChangedLock=true
if property == 'Neutral' then
-- if player changing to neutral
if entry['Player'].Neutral then
debugprint(entry['Player'].Name..'setting to neutral')
FindRemovePlayerFromTeam(entry)
entry['MyTeam']=nil
if not NeutralTeam then
debugprint(entry['Player'].Name..'creating neutral team')
AddNeutralTeam()
else
debugprint(entry['Player'].Name..'adding to neutral team')
AddPlayerToTeam(NeutralTeam,entry)
end
else -- else player switching to a team, or a weird edgecase
SetPlayerToTeam(entry)
end
elseif property == 'TeamColor' and not entry['Player'].Neutral and entry['Player'] ~= entry['MyTeam'] then
debugprint(entry['Player'].Name..'setting to new team')
SetPlayerToTeam(entry)
elseif property == 'Name' or property == 'MembershipType' then
entry['Frame']:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(entry['Player'].MembershipType,entry['Player'].Name)
entry['Frame'].Name = entry['Player'].Name
entry['Frame'].TitleFrame.Title.Text = entry['Player'].Name
if(entry['Frame'].BCLabel.Image ~= '') then
entry['Frame'].TitleFrame.Title.Position=UDim2.new(.01, 30, .1, 0)
end
if entry['Player'] == LocalPlayer then
entry['Frame'].TitleFrame.DropShadow.Text= entry['Player'].Name
ChangeHeaderName(entry['Player'].Name)
end
end
BaseUpdate()
PlayerChangedLock=false
end
function OnFriendshipChanged(player,friendStatus)
for _, entry in ipairs(PlayerFrames) do
if entry['Player']==player then
local nicon = getFriendStatusIcon(friendStatus)
if nicon == '' and entry['Frame'].FriendLabel.Image ~= '' then
entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position-UDim2.new(0,17,0,0)
elseif nicon ~= '' and entry['Frame'].FriendLabel.Image == '' then
entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position+UDim2.new(0,17,0,0)
end
entry['Frame'].FriendLabel.Image = nicon
return
end
end
end
LocalPlayer.FriendStatusChanged:connect(OnFriendshipChanged)
--[[
adds a neutral team if nessisary
Note: a lot of redundant code here, might want to refactor to share a function with insertteamframe
--]]
function AddNeutralTeam()
while NeutralTeamLock do debugprint('in neutral team 2 lock') wait() end
NeutralTeamLock = true
local defaultTeam = Instance.new('Team')
defaultTeam.TeamColor = BrickColor.new('White')
defaultTeam.Name = 'Neutral'
local nentry = {}
nentry['MyTeam'] = defaultTeam
nentry['MyPlayers'] = {}
nentry['Frame'] = MiddleTemplate:Clone()
WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = defaultTeam.Name
nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0)
nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0)
--nentry['Frame'].TitleFrame.Title.TextScaled=true
nentry['Frame'].TitleFrame.Title.Font = 'ArialBold'
nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0)
WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(StartDrag)
nentry['Frame'].ClickListener.BackgroundColor3 = Color3.new(1,1,1)
nentry['Frame'].ClickListener.BackgroundTransparency = .7
nentry['Frame'].ClickListener.AutoButtonColor=false
nentry['AutoHide'] = true
nentry['IsHidden'] = true
for _,i in pairs(PlayerFrames) do
if i['Player'].Neutral or not i['MyTeam'] then
AddPlayerToTeam(nentry,i)
end
end
if #nentry['MyPlayers'] > 0 then
NeutralTeam = nentry
UpdateMinimize()
BaseUpdate()
end
NeutralTeamLock = false
end
function RemoveNeutralTeam()
while NeutralTeamLock do debugprint('in neutral team lock') wait() end
NeutralTeamLock = true
NeutralTeam['Frame']:Destroy()
NeutralTeam=nil
RemoveMiddleBGFrame()
NeutralTeamLock = false
end
--[[
--]]
function TeamScoreChanged(entry,nscore)
WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nscore)
entry['TeamScore'] = nscore
end
--[[
called when child added to a team, used for autohide functionality
Note: still has teamscore, consiter removing
--]]
function TeamChildAdded(entry,nchild)
if nchild.Name == 'AutoHide' then
entry['AutoHide'] = true
elseif nchild.Name == 'TeamScore' then
WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nchild.Value)
entry['TeamScore'] = nchild.Value
nchild.Changed:connect(function() TeamScoreChanged(entry,nchild.Value) end)
end
end
--[[
called when child added to a team, used for autohide functionality
Note: still has teamscore, consiter removing
--]]
function TeamChildRemoved(entry,nchild)
if nchild.Name == 'AutoHide' then
entry['AutoHide'] = false
elseif nchild.Name == 'TeamScore' then
WaitForChild(entry['Frame'],'PlayerScore').Text = ""
entry['TeamScore'] = nil
end
end
--[[
creates team entry and frame for this team, sets up listeners for this team
adds any players intended for this team,Creates neutral team if this is the first team added
Note:might be best to break this into multiple functions to simplify
@Args:
nteam new team object added
--]]
function InsertTeamFrame(nteam)
while AddingFrameLock do debugprint('in adding team frame lock') wait(1/30) end
AddingFrameLock = true
local nentry = {}
nentry['MyTeam'] = nteam
nentry['MyPlayers'] = {}
nentry['Frame'] = MiddleTemplate:Clone()
WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = nteam.Name
nentry['Frame'].TitleFrame.Title.Font = 'ArialBold'
nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0)
nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0)
--nentry['Frame'].TitleFrame.Title.TextScaled=true
nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0)
WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(StartDrag)
nentry['Frame'].ClickListener.BackgroundColor3 = nteam.TeamColor.Color
nentry['Frame'].ClickListener.BackgroundTransparency = .7
nentry['Frame'].ClickListener.AutoButtonColor=false
AddId = AddId + 1
nentry['ID'] = AddId
nentry['AutoHide'] = false
if nteam:FindFirstChild('AutoHide') then
nentry['AutoHide'] = true
end
if nteam:FindFirstChild('TeamScore') then
TeamChildAdded(nentry,nteam.TeamScore)
end
nteam.ChildAdded:connect(function(nchild) TeamChildAdded(nentry,nchild) end)
nteam.ChildRemoved:connect(function(nchild) TeamChildRemoved(nentry,nchild) end)
for _,i in pairs(PlayerFrames) do
if not i['Player'].Neutral and i['Player'].TeamColor == nteam.TeamColor then
AddPlayerToTeam(nentry,i)
end
end
nentry['IsHidden'] = false
if not nentry['AutoHide'] or #nentry['MyPlayers'] > 0 then
nentry['Frame'].Parent = ListFrame
nentry['Frame']:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0), "Out", "Quad", .5,true)
AddMiddleBGFrame()
else
nentry['IsHidden'] = true
nentry['Frame'].Parent = nil
end
table.insert(TeamFrames,nentry)
UpdateMinimize()
BaseUpdate()
if #TeamFrames == 1 and not NeutralTeam then
AddNeutralTeam()
end
AddingFrameLock = false
end
--[[
removes team from team list
@Args:
nteam Teamobject to remove
--]]
function RemoveTeamFrame(nteam)
while AddingFrameLock do debugprint('in removing team frame lock') wait(1/30) end
AddingFrameLock = true
if IsMinimized.Value then
-- ListFrame.Position = ListFrame.Position + UDim2.new(0,0,MiddleTemplate.Size.Y.Scale,0)
end
local myEntry
for i,key in ipairs(TeamFrames) do
if nteam == key['MyTeam'] then
myEntry = key
key['Frame']:Destroy()
table.remove(TeamFrames,i)
end
end
if #TeamFrames==0 then
if NeutralTeam then
RemoveNeutralTeam()
end
end
for i,key in ipairs(myEntry['MyPlayers']) do
RemovePlayerFromTeam(myEntry,i)
PlayerChanged(key, 'TeamColor')
end
RemoveMiddleBGFrame()
BaseUpdate()
AddingFrameLock = false
end
function TeamAdded(nteam)
InsertTeamFrame(nteam)
end
function TeamRemoved(nteam)
RemoveTeamFrame(nteam)
end
---------------------------------
--[[
called when ANYTHING changes the state of the playerlist
re-sorts everything,assures correct positions of all elements
--]]
function BaseUpdate()
while BaseUpdateLock do debugprint('in baseupdate lock') wait(1/30) end
BaseUpdateLock = true
if #TeamFrames == 0 then
PlayerListModeUpdate()
else
TeamListModeUpdate()
end
for i,key in ipairs(MiddleFrames) do
if key.Parent ~= nil then
key:TweenPosition(UDim2.new(.5,0,((#MiddleFrames - (i)) * key.Size.Y.Scale),0), "Out", "Quad", .9,true)
end
end
if not IsMinimized.Value and #MiddleFrames>DefaultEntriesOnScreen then
UpdateScrollPosition()
end
UpdateScrollBarVisibility()
debugprint('EndBaseUpdate')
BaseUpdateLock = false
end
--[[
code for attaching tab key to maximizing player list
--]]
game.GuiService:AddKey("\t")
local LastTabTime = time()
game.GuiService.KeyPressed:connect(
function(key)
if key == "\t" then
debugprint('caught tab key')
local modalCheck, isModal = pcall(function() return game.GuiService.IsModalDialog end)
if modalCheck == false or (modalCheck and isModal == false) then
if time() - LastTabTime > 0.4 then
LastTabTime = time()
if IsTabified.Value then
if not IsMaximized.Value then
ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Quad',1,true)
IsMaximized.Value = true
else
ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Quad',1,true)
IsMaximized.Value = false
IsMinimized.Value=true
end
else
ToggleMaximize()
end
end
end
end
end)
----------------------------
-- Hookups and initialization
----------------------------
function debugPlayerAdd(p)
InsertPlayerFrame(p)
end
while not game:GetService('Teams') do wait(1/30) debugprint('Waiting For Teams') end
for _,i in pairs(game.Teams:GetTeams()) do TeamAdded(i) end
for _,i in pairs(Players:GetPlayers()) do Spawn(function() debugPlayerAdd(i) end) end--InsertPlayerFrame(i) end
game.Teams.ChildAdded:connect(TeamAdded)
game.Teams.ChildRemoved:connect(TeamRemoved)
Players.ChildAdded:connect(function(tplayer) Spawn(function() debugPlayerAdd(tplayer) end) end)--InsertPlayerFrame)
InitReportAbuse()
BaseUpdate()
--UGGGLY,find a better way later
wait(2)
IsPersonalServer= not not game.Workspace:FindFirstChild("PSVariable")
----------------------------
-- Running Logic
----------------------------
--debug stuffs, will only run for 'newplayerlistisbad'
--REMOVEME
if LocalPlayer.Name == 'newplayerlistisbad' then
debugFrame.Parent = ScreenGui
Spawn(function()
while true do
local str_players=''
for _,i in pairs(game.Players:GetPlayers()) do
str_players= str_players .." " .. i.Name
end
debugplayers.Text=str_players
wait(.5)
end
end)
end
function EnsureValidity()
while true do
--make sure all players are in the player list
--and make sure there are no entries that corespond to non-existant players
local unfoundEntries={}
for k,v in pairs(PlayerFrames) do
unfoundEntries[k] = v
end
--for all players
for _,i in pairs(Players:GetPlayers()) do
local foundPlayer=false
--for all known players
for entryIndex,j in pairs(PlayerFrames) do
-- if I know about this player, tag it
if i==j['Player'] then
foundPlayer=true
unfoundEntries[entryIndex]=nil
end
end
--if this player is not known
if not foundPlayer then
wait(.5)
--do a double check
for _,j in pairs(PlayerFrames) do
if i==j['Player'] then
foundPlayer=true
end
end
if not foundPlayer then
InsertPlayerFrame(i)
debugOutput.Text= "Manual Insertion! " .. i.Name
end
end
end
--for any additional entries, never found, remove them
for _,j in pairs(unfoundEntries) do
RemovePlayerFrame(j['Player'])
debugOutput.Text= "Player Manual Removal! " ..j['Player'].Name
end
wait(1/30)
--make sure there are no gaps or overlaps in the playerlist
while GetEntryListLength()>#MiddleFrameBackgrounds do
AddMiddleBGFrame()
end
while GetEntryListLength()<#MiddleFrameBackgrounds do
RemoveMiddleBGFrame()
end
wait(1/30)
--remove neutral team if it shouldn't exist
if NeutralTeam and (#NeutralTeam['MyPlayers']==0 or #TeamFrames==0) then
wait(.5)
if NeutralTeam and (#NeutralTeam['MyPlayers']==0 or #TeamFrames==0) then
RemoveNeutralTeam()
debugOutput.Text= "Manual removal of neutral team! "
end
end
wait(1/30)
--do a base update, just ot be sure
BaseUpdate()
wait(1/30)
end
end
--quick fix running logic, PLEASE LET ME REPLACE LATER
--Spawn(EnsureValidity)
-
true
TimeoutScript
wait(5)
local dialog = script.Parent
if dialog:IsA("Dialog") then
dialog.InUse = false
end
script:Remove()
-
false
ResetCommand
function onChatted(msg, speaker)
source = string.lower(speaker.Name)
msg = string.lower(msg)
-- Note: This one is NOT caps sensitive
if msg == "!!!reset" then
speaker.Character.Humanoid.Health = 0
end
end
function onPlayerEntered(newPlayer)
newPlayer.Chatted:connect(function(msg) onChatted(msg, newPlayer) end)
end
game.Players.ChildAdded:connect(onPlayerEntered)
-
true
ReenableDialogScript
wait(5)
local dialog = script.Parent
if dialog:IsA("Dialog") then
dialog.InUse = false
end
script:Remove()
-
Chat
-
false
ChatScript
--rbxsig%JEfYnuC18EOdJ5gffQHlphGalfinD7ZNa+lFyYhYGQmQKlc/17N4PkAlQOjn7p5BdnyvBX3SUw7sweW90l/eUVzzt3dV/Vm63x6KIHjG8HLPwkxKCrtLbV4Mnw5q6mIS1A3GYXDkd3HG5iKgRfQHlCaCut4VQXquAtSITfkUJhc=%
--rbxassetid%60595411%
local t = {}
--JSON Encoder and Parser for Lua 5.1
--
--Copyright 2007 Shaun Brown (http://www.chipmunkav.com)
--All Rights Reserved.
--Permission is hereby granted, free of charge, to any person
--obtaining a copy of this software to deal in the Software without
--restriction, including without limitation the rights to use,
--copy, modify, merge, publish, distribute, sublicense, and/or
--sell copies of the Software, and to permit persons to whom the
--Software is furnished to do so, subject to the following conditions:
--The above copyright notice and this permission notice shall be
--included in all copies or substantial portions of the Software.
--If you find this software useful please give www.chipmunkav.com a mention.
--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
--EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
--OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
--IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
--ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
--CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
--CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local string = string
local math = math
local table = table
local error = error
local tonumber = tonumber
local tostring = tostring
local type = type
local setmetatable = setmetatable
local pairs = pairs
local ipairs = ipairs
local assert = assert
local Chipmunk = Chipmunk
local StringBuilder = {
buffer = {}
}
function StringBuilder:New()
local o = {}
setmetatable(o, self)
self.__index = self
o.buffer = {}
return o
end
function StringBuilder:Append(s)
self.buffer[#self.buffer+1] = s
end
function StringBuilder:ToString()
return table.concat(self.buffer)
end
local JsonWriter = {
backslashes = {
['\b'] = "\\b",
['\t'] = "\\t",
['\n'] = "\\n",
['\f'] = "\\f",
['\r'] = "\\r",
['"'] = "\\\"",
['\\'] = "\\\\",
['/'] = "\\/"
}
}
function JsonWriter:New()
local o = {}
o.writer = StringBuilder:New()
setmetatable(o, self)
self.__index = self
return o
end
function JsonWriter:Append(s)
self.writer:Append(s)
end
function JsonWriter:ToString()
return self.writer:ToString()
end
function JsonWriter:Write(o)
local t = type(o)
if t == "nil" then
self:WriteNil()
elseif t == "boolean" then
self:WriteString(o)
elseif t == "number" then
self:WriteString(o)
elseif t == "string" then
self:ParseString(o)
elseif t == "table" then
self:WriteTable(o)
elseif t == "function" then
self:WriteFunction(o)
elseif t == "thread" then
self:WriteError(o)
elseif t == "userdata" then
self:WriteError(o)
end
end
function JsonWriter:WriteNil()
self:Append("null")
end
function JsonWriter:WriteString(o)
self:Append(tostring(o))
end
function JsonWriter:ParseString(s)
self:Append('"')
self:Append(string.gsub(s, "[%z%c\\\"/]", function(n)
local c = self.backslashes[n]
if c then return c end
return string.format("\\u%.4X", string.byte(n))
end))
self:Append('"')
end
function JsonWriter:IsArray(t)
local count = 0
local isindex = function(k)
if type(k) == "number" and k > 0 then
if math.floor(k) == k then
return true
end
end
return false
end
for k,v in pairs(t) do
if not isindex(k) then
return false, '{', '}'
else
count = math.max(count, k)
end
end
return true, '[', ']', count
end
function JsonWriter:WriteTable(t)
local ba, st, et, n = self:IsArray(t)
self:Append(st)
if ba then
for i = 1, n do
self:Write(t[i])
if i < n then
self:Append(',')
end
end
else
local first = true;
for k, v in pairs(t) do
if not first then
self:Append(',')
end
first = false;
self:ParseString(k)
self:Append(':')
self:Write(v)
end
end
self:Append(et)
end
function JsonWriter:WriteError(o)
error(string.format(
"Encoding of %s unsupported",
tostring(o)))
end
function JsonWriter:WriteFunction(o)
if o == Null then
self:WriteNil()
else
self:WriteError(o)
end
end
local StringReader = {
s = "",
i = 0
}
function StringReader:New(s)
local o = {}
setmetatable(o, self)
self.__index = self
o.s = s or o.s
return o
end
function StringReader:Peek()
local i = self.i + 1
if i <= #self.s then
return string.sub(self.s, i, i)
end
return nil
end
function StringReader:Next()
self.i = self.i+1
if self.i <= #self.s then
return string.sub(self.s, self.i, self.i)
end
return nil
end
function StringReader:All()
return self.s
end
local JsonReader = {
escapes = {
['t'] = '\t',
['n'] = '\n',
['f'] = '\f',
['r'] = '\r',
['b'] = '\b',
}
}
function JsonReader:New(s)
local o = {}
o.reader = StringReader:New(s)
setmetatable(o, self)
self.__index = self
return o;
end
function JsonReader:Read()
self:SkipWhiteSpace()
local peek = self:Peek()
if peek == nil then
error(string.format(
"Nil string: '%s'",
self:All()))
elseif peek == '{' then
return self:ReadObject()
elseif peek == '[' then
return self:ReadArray()
elseif peek == '"' then
return self:ReadString()
elseif string.find(peek, "[%+%-%d]") then
return self:ReadNumber()
elseif peek == 't' then
return self:ReadTrue()
elseif peek == 'f' then
return self:ReadFalse()
elseif peek == 'n' then
return self:ReadNull()
elseif peek == '/' then
self:ReadComment()
return self:Read()
else
return nil
end
end
function JsonReader:ReadTrue()
self:TestReservedWord{'t','r','u','e'}
return true
end
function JsonReader:ReadFalse()
self:TestReservedWord{'f','a','l','s','e'}
return false
end
function JsonReader:ReadNull()
self:TestReservedWord{'n','u','l','l'}
return nil
end
function JsonReader:TestReservedWord(t)
for i, v in ipairs(t) do
if self:Next() ~= v then
error(string.format(
"Error reading '%s': %s",
table.concat(t),
self:All()))
end
end
end
function JsonReader:ReadNumber()
local result = self:Next()
local peek = self:Peek()
while peek ~= nil and string.find(
peek,
"[%+%-%d%.eE]") do
result = result .. self:Next()
peek = self:Peek()
end
result = tonumber(result)
if result == nil then
error(string.format(
"Invalid number: '%s'",
result))
else
return result
end
end
function JsonReader:ReadString()
local result = ""
assert(self:Next() == '"')
while self:Peek() ~= '"' do
local ch = self:Next()
if ch == '\\' then
ch = self:Next()
if self.escapes[ch] then
ch = self.escapes[ch]
end
end
result = result .. ch
end
assert(self:Next() == '"')
local fromunicode = function(m)
return string.char(tonumber(m, 16))
end
return string.gsub(
result,
"u%x%x(%x%x)",
fromunicode)
end
function JsonReader:ReadComment()
assert(self:Next() == '/')
local second = self:Next()
if second == '/' then
self:ReadSingleLineComment()
elseif second == '*' then
self:ReadBlockComment()
else
error(string.format(
"Invalid comment: %s",
self:All()))
end
end
function JsonReader:ReadBlockComment()
local done = false
while not done do
local ch = self:Next()
if ch == '*' and self:Peek() == '/' then
done = true
end
if not done and
ch == '/' and
self:Peek() == "*" then
error(string.format(
"Invalid comment: %s, '/*' illegal.",
self:All()))
end
end
self:Next()
end
function JsonReader:ReadSingleLineComment()
local ch = self:Next()
while ch ~= '\r' and ch ~= '\n' do
ch = self:Next()
end
end
function JsonReader:ReadArray()
local result = {}
assert(self:Next() == '[')
local done = false
if self:Peek() == ']' then
done = true;
end
while not done do
local item = self:Read()
result[#result+1] = item
self:SkipWhiteSpace()
if self:Peek() == ']' then
done = true
end
if not done then
local ch = self:Next()
if ch ~= ',' then
error(string.format(
"Invalid array: '%s' due to: '%s'",
self:All(), ch))
end
end
end
assert(']' == self:Next())
return result
end
function JsonReader:ReadObject()
local result = {}
assert(self:Next() == '{')
local done = false
if self:Peek() == '}' then
done = true
end
while not done do
local key = self:Read()
if type(key) ~= "string" then
error(string.format(
"Invalid non-string object key: %s",
key))
end
self:SkipWhiteSpace()
local ch = self:Next()
if ch ~= ':' then
error(string.format(
"Invalid object: '%s' due to: '%s'",
self:All(),
ch))
end
self:SkipWhiteSpace()
local val = self:Read()
result[key] = val
self:SkipWhiteSpace()
if self:Peek() == '}' then
done = true
end
if not done then
ch = self:Next()
if ch ~= ',' then
error(string.format(
"Invalid array: '%s' near: '%s'",
self:All(),
ch))
end
end
end
assert(self:Next() == "}")
return result
end
function JsonReader:SkipWhiteSpace()
local p = self:Peek()
while p ~= nil and string.find(p, "[%s/]") do
if p == '/' then
self:ReadComment()
else
self:Next()
end
p = self:Peek()
end
end
function JsonReader:Peek()
return self.reader:Peek()
end
function JsonReader:Next()
return self.reader:Next()
end
function JsonReader:All()
return self.reader:All()
end
function Encode(o)
local writer = JsonWriter:New()
writer:Write(o)
return writer:ToString()
end
function Decode(s)
local reader = JsonReader:New(s)
return reader:Read()
end
function Null()
return Null
end
-------------------- End JSON Parser ------------------------
t.DecodeJSON = function(jsonString)
if type(jsonString) == "string" then
return Decode(jsonString)
end
print("RbxUtil.DecodeJSON expects string argument!")
return nil
end
t.EncodeJSON = function(jsonTable)
return Encode(jsonTable)
end
------------------------------Terrain Utilities Begin--------------------------------
--makes a wedge at location x, y, z
--sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was
--returns true if made a wedge, false if the cell remains a block
t.MakeWedge = function(x, y, z, defaultmaterial)
local c = game:GetService("TerrainService")
--gather info about all the cells around x, y, z
surroundings = {} --surroundings is a 3 x 3 x 3 array of the material of the cells adjacent to x, y, z
for i = x - 1, x + 1 do
surroundings[i] = {}
for j = y - 1, y + 1 do
surroundings[i][j] = {}
for k = z - 1, z + 1 do
print("seeing the latest")
local material = nil
local wedge = nil
local rotation = nil
material, wedge, rotation = c:GetCellFull(i, j, k)
surroundings[i][j][k] = material
end
end
end
--make some useful arrays and counters
local sides = {} --sides is an array of the material of the 4 adjacent sides
sides[0] = surroundings[x - 1][y][z]
sides[1] = surroundings[x][y][z + 1]
sides[2] = surroundings[x + 1][y][z]
sides[3] = surroundings[x][y][z - 1]
local adjacentSides = 0
for n = 0, 3 do
if sides[n] > 0 then
adjacentSides = adjacentSides + 1
end
end
local sidesAbove = {} --sides is an array of the material of the 4 adjacent sides 1 height above
sidesAbove[0] = surroundings[x - 1][y + 1][z]
sidesAbove[1] = surroundings[x][y + 1][z + 1]
sidesAbove[2] = surroundings[x + 1][y + 1][z]
sidesAbove[3] = surroundings[x][y + 1][z - 1]
local adjacentSidesAbove = 0
for n = 0, 3 do
if sidesAbove[n] > 0 then
adjacentSidesAbove = adjacentSidesAbove + 1
end
end
local corners = {} --corners is an array of the material of the 4 adjacent corners
corners[0] = surroundings[x - 1][y][z - 1]
corners[1] = surroundings[x - 1][y][z + 1]
corners[2] = surroundings[x + 1][y][z + 1]
corners[3] = surroundings[x + 1][y][z - 1]
local adjacentCorners = 0
for n = 0, 3 do
if corners[n] > 0 then
adjacentCorners = adjacentCorners + 1
end
end
local cornersAbove = {} --corners is an array of the material of the 4 adjacent corners 1 height above
cornersAbove[0] = surroundings[x - 1][y + 1][z - 1]
cornersAbove[1] = surroundings[x - 1][y + 1][z + 1]
cornersAbove[2] = surroundings[x + 1][y + 1][z + 1]
cornersAbove[3] = surroundings[x + 1][y + 1][z - 1]
local adjacentCornersAbove = 0
for n = 0, 3 do
if cornersAbove[n] > 0 then
adjacentCornersAbove = adjacentCornersAbove + 1
end
end
--determine what type of wedge to make
local material = nil
local wedge = nil
local rotation = nil
if defaultmaterial then
material = defaultmaterial
else
material, wedge, rotation = c:GetCellFull(x, y, z) --start with the existing material, wedge, and rotation
end
wedge = 0 --default wedge is a block
rotation = 0 --default rotation is 0
--type 1: 45 degree ramp //must not have a block on top and must have a block under, and be surrounded by 1 side; or 3 sides and the 2 corners between them
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
if adjacentSides == 1 then
for n = 0, 3 do
if sides[n] > 0 then
wedge = 1
rotation = (n + 1) % 4
c:SetCellFull(x, y, z, material, wedge, rotation)
return true
end
end
elseif adjacentSides == 3 then
for n = 0, 3 do
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and corners[(n + 2) % 4] > 0 and sides[(n + 2) % 4] > 0 then
wedge = 1
rotation = (n + 2) % 4
c:SetCellFull(x, y, z, material, wedge, rotation)
return true
end
end
end
end
--type 2: 45 degree corner //must not have a block on top and must have a block under, and be surrounded by 2 sides and the 1 corner between them; or 3 sides and 1 corner between 2 of them (facing towards that corner)
if surroundings[x][y + 1][z] == 0 and surroundings[x][y - 1][z] > 0 then
for n = 0, 3 do
if sides[n] > 0 and corners[(n + 1) % 4] > 0 and sides[(n + 1) % 4] > 0 and (adjacentSides == 2 or (adjacentSides == 3 and (corners[(n + 3) % 4] > 0 or (sides[(n + 2) % 4] > 0 and corners[(n + 2) % 4] > 0) or (sides[(n + 3) % 4] > 0 and corners[n] > 0)))) then
wedge = 2
rotation = (n + 2) % 4
c:SetCellFull(x, y, z, material, wedge, rotation)
return true
end
end
end
--type 3: 45 degree inverse corner //surrounded by three sides or 4 sides and 3 corners, with nothing above or else a block on top surrounded on 2 sides and the corner between them
if adjacentSides == 3 and surroundings[x][y + 1][z] > 0 then
if adjacentCorners > 1 then
for n = 0, 3 do
if (corners[n] == 0 or cornersAbove[n] == 0) and (sides[(n - 1) % 4] == 0 or sides[n] == 0) and (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0) then
wedge = 3
rotation = (n + 3) % 4
c:SetCellFull(x, y, z, material, wedge, rotation)
return true
end
end
end
elseif adjacentSides == 4 and adjacentCorners == 3 then
for n = 0, 3 do
if corners[n] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] > 0 and cornersAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] == 0)) then
wedge = 3
rotation = (n + 3) % 4
c:SetCellFull(x, y, z, material, wedge, rotation)
return true
end
end
end
--type 4: half a cube, as if it were cut diagonally from front to back //surrounded by 2 sides
if adjacentSides == 2 and adjacentCorners < 4 then
for n = 0, 3 do
if sides[n] == 0 and sides[(n + 1) % 4] == 0 and (surroundings[x][y + 1][z] == 0 or (sidesAbove[n] == 0 and sidesAbove[(n + 1) % 4] == 0 and sidesAbove[(n + 2) % 4] > 0 and sidesAbove[(n + 3) % 4] > 0)) then
wedge = 4
rotation = n
c:SetCellFull(x, y, z, material, wedge, rotation)
return true
end
end
end
c:SetCellFull(x, y, z, material, wedge, rotation)
return false
end
-----------------------------Terrain Utilities End-----------------------------
t.Help =
function(funcNameOrFunc)
--input argument can be a string or a function. Should return a description (of arguments and expected side effects)
if funcNameOrFunc == "DecodeJSON" or funcNameOrFunc == t.DecodeJSON then
return "Function DecodeJSON. " ..
"Arguments: (string). " ..
"Side effect: returns a table with all parsed JSON values"
end
if funcNameOrFunc == "EncodeJSON" or funcNameOrFunc == t.EncodeJSON then
return "Function EncodeJSON. " ..
"Arguments: (table). " ..
"Side effect: returns a string composed of argument table in JSON data format"
end
if funcNameOrFunc == "MakeWedge" or funcNameOrFunc == t.MakeWedge then
return "Function MakeWedge. " ..
"Arguments: (x, y, z, [default material]). " ..
"Description: Makes a wedge at location x, y, z. Sets cell x, y, z to default material if parameter is provided, if not sets cell x, y, z to be whatever material it previously was. Returns true if made a wedge, false if the cell remains a block "
end
end
--rbxsig%REvu/wlKsFpV+wGhx4ZIeoKQ3ajJIMa8dt7TmxHPEQ3UyELsZVYT0DQiFiH7ICCEoiF9Yj9pNuB6DvyP739SU78jRrPa3Ln1aJHwdBur+X9TWjVvHDiHrezRhmWvXOIBhmw+/xoj+88xIoZABu36+kLyoHQDBbg8qrTf0CUZv5c=%
--rbxassetid%97188756%
--[[
//FileName: ChatScript.LUA
//Written by: Sorcus
//Description: Code for lua side chat on ROBLOX. Supports Scrolling.
//NOTE: If you find any bugs or inaccuracies PM Sorcus on ROBLOX or @Canavus on Twitter
]]
-- Utility functions + Globals
local function WaitForChild(parent, childName)
while parent:FindFirstChild(childName) == nil do
parent.ChildAdded:wait(0.03)
end
return parent[childName]
end
function Create(guiType)
return function(data)
local obj = Instance.new(guiType)
for k, v in pairs(data) do
if type(k) == 'number' then
v.Parent = obj
else
obj[k] = v
end
end
return obj
end
end
local function typedef(obj)
return obj
end
local function IsPhone()
end
-- Users can use enough white spaces to spoof chatting as other players
-- This function removes trailing and leading white spaces
-- AFAIK, there is no reason for spam white spaces
local function StringTrim(str)
-- %S is whitespaces
-- When we find the first non space character defined by ^%s
-- we yank out anything in between that and the end of the string
-- Everything else is replaced with %1 which is essentially nothing
return (str:gsub("^%s*(.-)%s*$", "%1"))
end
while Game.Players.LocalPlayer == nil do wait(0.03) end
local Player = Game.Players.LocalPlayer
while Player.Character == nil do wait(0.03) end
local RbxUtility = t
local Gui = typedef(RbxUtility)
local Camera = Game.Workspace.CurrentCamera
-- Services
local CoreGuiService = Game:GetService('CoreGui')
local PlayersService = Game:GetService('Players')
local DebrisService= Game:GetService('Debris')
local GuiService = Game:GetService('GuiService')
-- Lua Enums
local Enums do
Enums = {}
local EnumName = {} -- used as unique key for enum name
local enum_mt = {
__call = function(self,value)
return self[value] or self[tonumber(value)]
end;
__index = {
GetEnumItems = function(self)
local t = {}
for i,item in pairs(self) do
if type(i) == 'number' then
t[#t+1] = item
end
end
table.sort(t,function(a,b) return a.Value < b.Value end)
return t
end;
};
__tostring = function(self)
return "Enum." .. self[EnumName]
end;
}
local item_mt = {
__call = function(self,value)
return value == self or value == self.Name or value == self.Value
end;
__tostring = function(self)
return "Enum." .. self[EnumName] .. "." .. self.Name
end;
}
function CreateEnum(enumName)
return function(t)
local e = {[EnumName] = enumName}
for i,name in pairs(t) do
local item = setmetatable({Name=name,Value=i,Enum=e,[EnumName]=enumName},item_mt)
e[i] = item
e[name] = item
e[item] = item
end
Enums[enumName] = e
return setmetatable(e, enum_mt)
end
end
end
---------------------------------------------------
------------------ Input class --------------------
local Input = {
Mouse = Player:GetMouse(),
Speed = 0,
Simulating = false,
Configuration = {
DefaultSpeed = 1
},
UserIsScrolling = false
}
---------------------------------------------------
------------------ Chat class --------------------
local Chat = {
ChatColors = {
BrickColor.new("Bright red"),
BrickColor.new("Bright blue"),
BrickColor.new("Earth green"),
BrickColor.new("Bright violet"),
BrickColor.new("Bright orange"),
BrickColor.new("Bright yellow"),
BrickColor.new("Light reddish violet"),
BrickColor.new("Brick yellow"),
},
Gui = nil,
Frame = nil,
RenderFrame = nil,
TapToChatLabel = nil,
ClickToChatButton = nil,
ScrollingLock = false,
EventListener = nil,
-- This is actually a ring buffer
-- Meaning at hitting the historyLength it wraps around
-- Reuses the text objects, so chat atmost uses 100 text objects
MessageQueue = {},
-- Stores all the values for configuring chat
Configuration = {
FontSize = Enum.FontSize.Size12, -- 10 is good
-- Also change this when you are changing the above, this is suboptimal but so is our interface to find FontSize
NumFontSize = 12,
HistoryLength = 20, -- stores up to 50 of the last chat messages for you to scroll through,
Size = UDim2.new(0.38, 0, 0.20, 0),
MessageColor = Color3.new(1, 1, 1),
AdminMessageColor = Color3.new(1, 215/255, 0),
XScale = 0.025,
LifeTime = 45,
Position = UDim2.new(0, 2, 0.05, 0),
DefaultTweenSpeed = 0.15,
},
-- This could be redone by just using the previous and next fields of the Queue
-- But the iterators cause issues, will be optimized later
SlotPositions_List = {},
-- To precompute and store all player null strings since its an expensive process
CachedSpaceStrings_List = {},
MouseOnFrame = false,
GotFocus = false,
Messages_List = {},
MessageThread = nil,
-- changing anything here might and WILL get you banned. - iagoMAO --
Admins_List = {'iagoMAO', 'Carrot', 'winsupermario1234', 'Bitl', 'QuackIAttack', 'khanglegos', 'Nukley', 'OliverA',
'Raymonf', 'coke', 'TheLivingBee', 'Peridorky', 'romulo27', 'robloxtester', 'CPunch', 'connor'
},
SafeChat_List = {
['Use the Chat menu to talk to me.'] = {'/sc 0', true},
['I can only see menu chats.'] = {'/sc 1', true},
['Hello'] = {
['Hi'] = {'/sc 2_0', true, ['Hi there!'] = true, ['Hi everyone'] = true},
['Howdy'] = {'/sc 2_1', true, ['Howdy partner!'] = true},
['Greetings'] = {'/sc 2_2', true, ['Greetings everyone'] = true, ['Greetings Robloxians!'] = true, ['Seasons greetings!'] = true},
['Welcome'] = {'/sc 2_3', true, ['Welcome to my place'] = true, ['Welcome to my barbeque'] = true, ['Welcome to our base'] = true},
['Hey there!'] = {'/sc 2_4', true},
['What\'s up?'] = {'/sc 2_5', true, ['How are you doing?'] = true, ['How\'s it going?'] = true, ['What\'s new?'] = true},
['Good day'] = {'/sc 2_6', true, ['Good morning'] = true, ['Good evening'] = true, ['Good afternoon'] = true, ['Good night'] = true},
['Silly'] = {'/sc 2_7', true, ['Waaaaaaaz up?!'] = true, ['Hullo!'] = true, ['Behold greatness, mortals!'] = true, ['Pardon me, is this Sparta?'] = true, ['THIS IS SPARTAAAA!'] = true},
['Happy Holidays!'] = {'/sc 2_8', true, ['Happy New Year!'] = true,
['Happy Valentine\'s Day!'] = true,
['Beware the Ides of March!'] = true,
['Happy St. Patrick\'s Day!'] = true,
['Happy Easter!'] = true,
['Happy Earth Day!'] = true,
['Happy 4th of July!'] = true,
['Happy Thanksgiving!'] = true,
['Happy Halloween!'] = true,
['Happy Hanukkah!'] = true,
['Merry Christmas!'] = true,
['Happy Halloween!'] = true,
['Happy Earth Day!'] = true,
['Happy May Day!'] = true,
['Happy Towel Day!'] = true,
['Happy ROBLOX Day!'] = true,
['Happy LOL Day!'] = true },
[1] = '/sc 2'
},
['Goodbye'] = {
['Good Night']= {'/sc 3_0', true,
['Sweet dreams'] = true,
['Go to sleep!'] = true,
['Lights out!'] = true,
['Bedtime'] = true,
['Going to bed now'] = true},
['Later']= {'/sc 3_1', true,
['See ya later'] = true,
['Later gator!'] = true,
['See you tomorrow'] = true},
['Bye'] = {'/sc 3_2', true, ['Hasta la bye bye!'] = true},
['I\'ll be right back'] = {'/sc 3_3', true},
['I have to go'] = {'/sc 3_4', true},
['Farewell'] = {'/sc 3_5', true, ['Take care'] = true, ['Have a nice day'] = true, ['Goodluck!'] = true, ['Ta-ta for now!'] = true},
['Peace'] = {'/sc 3_6', true, ['Peace out!'] = true, ['Peace dudes!'] = true, ['Rest in pieces!'] = true},
['Silly'] = {'/sc 3_7', true,
['To the batcave!'] = true,
['Over and out!'] = true,
['Happy trails!'] = true,
['I\'ve got to book it!'] = true,
['Tootles!'] = true,
['Smell you later!'] = true,
['GG!'] = true,
['My house is on fire! gtg.'] = true},
[1] = '/sc 3'
},
['Friend'] ={
['Wanna be friends?'] = {'/sc 4_0', true},
['Follow me'] = {'/sc 4_1', true, ['Come to my place!'] = true, ['Come to my base!'] = true, ['Follow me, team!'] = true, ['Follow me'] = true},
['Your place is cool'] = {'/sc 4_2', true, ['Your place is fun'] = true, ['Your place is awesome'] = true, ['Your place looks good'] = true, ['This place is awesome!'] = true},
['Thank you'] = {'/sc 4_3', true, ['Thanks for playing'] = true, ['Thanks for visiting'] = true, ['Thanks for everything'] = true, ['No, thank you'] = true, ['Thanx'] = true},
['No problem'] = {'/sc 4_4', true, ['Don\'t worry'] = true, ['That\'s ok'] = true, ['np'] = true},
['You are ...'] = {'/sc 4_5', true,
['You are great!'] = true,
['You are good!'] = true,
['You are cool!'] = true,
['You are funny!'] = true,
['You are silly!'] = true,
['You are awesome!'] = true,
['You are doing something I don\'t like, please stop'] = true
},
['I like ...'] = {'/sc 4_6', true, ['I like your name'] = true, ['I like your shirt'] = true, ['I like your place'] = true, ['I like your style'] = true,
['I like you'] = true, ['I like items'] = true, ['I like money'] = true},
['Sorry'] = {'/sc 4_7', true, ['My bad!'] = true, ['I\'m sorry'] = true, ['Whoops!'] = true, ['Please forgive me.'] = true, ['I forgive you.'] = true,
['I didn\'t mean to do that.'] = true, ['Sorry, I\'ll stop now.'] = true},
[1] = '/sc 4'
},
['Questions'] = {
['Who?'] = {'/sc 5_0', true, ['Who wants to be my friend?'] = true, ['Who wants to be on my team?'] = true, ['Who made this brilliant game?'] = true},
['What?'] = {'/sc 5_1', true, ['What is your favorite animal?'] = true, ['What is your favorite game?'] = true, ['What is your favorite movie?'] = true,
['What is your favorite TV show?'] = true, ['What is your favorite music?'] = true, ['What are your hobbies?'] = true, ['LOLWUT?'] = true},
['When?'] = {'/sc 5_2', true, ['When are you online?'] = true, ['When is the new version coming out?'] = true, ['When can we play again?'] = true, ['When will your place be done?'] = true},
['Where?'] = {'/sc 5_3', true, ['Where do you want to go?'] = true, ['Where are you going?'] = true, ['Where am I?!'] = true, ['Where did you go?'] = true},
['How?'] = {'/sc 5_4', true, ['How are you today?'] = true, ['How did you make this cool place?'] = true, ['LOLHOW?'] = true},
['Can I...'] = {'/sc 5_5', true, ['Can I have a tour?'] = true, ['Can I be on your team?'] = true, ['Can I be your friend?'] = true, ['Can I try something?'] = true,
['Can I have that please?'] = true, ['Can I have that back please?'] = true, ['Can I have borrow your hat?'] = true, ['Can I have borrow your gear?'] = true},
[1] = '/sc 5'
},
['Answers'] = {
['You need help?'] = {'/sc 6_0', true, ['Check out the news section'] = true, ['Check out the help section'] = true, ['Read the wiki!'] = true,
['All the answers are in the wiki!'] = true, ['I will help you with this.'] = true},
['Some people ...'] = {'/sc 6_1', true, ['Me'] = true, ['Not me'] = true, ['You'] = true, ['All of us'] = true, ['Everyone but you'] = true, ['Builderman!'] = true,
['Telamon!'] = true, ['My team'] = true, ['My group'] = true, ['Mom'] = true, ['Dad'] = true, ['Sister'] = true, ['Brother'] = true, ['Cousin'] = true,
['Grandparent'] = true, ['Friend'] = true},
['Time ...'] = {'/sc 6_2', true, ['In the morning'] = true, ['In the afternoon'] = true, ['At night'] = true, ['Tomorrow'] = true, ['This week'] = true, ['This month'] = true,
['Sometime'] = true, ['Sometimes'] = true, ['Whenever you want'] = true, ['Never'] = true, ['After this'] = true, ['In 10 minutes'] = true, ['In a couple hours'] = true,
['In a couple days'] = true},
['Animals'] = {'/sc 6_3', true,
['Cats'] = {['Lion'] = true, ['Tiger'] = true, ['Leopard'] = true, ['Cheetah'] = true},
['Dogs'] = {['Wolves'] = true, ['Beagle'] = true, ['Collie'] = true, ['Dalmatian'] = true, ['Poodle'] = true, ['Spaniel'] = true,
['Shepherd'] = true, ['Terrier'] = true, ['Retriever'] = true},
['Horses'] = {['Ponies'] = true, ['Stallions'] = true, ['Pwnyz'] = true},
['Reptiles'] = {['Dinosaurs'] = true, ['Lizards'] = true, ['Snakes'] = true, ['Turtles!'] = true},
['Hamster'] = true,
['Monkey'] = true,
['Bears'] = true,
['Fish'] = {['Goldfish'] = true, ['Sharks'] = true, ['Sea Bass'] = true, ['Halibut'] = true, ['Tropical Fish'] = true},
['Birds'] = {['Eagles'] = true, ['Penguins'] = true, ['Parakeets'] = true, ['Owls'] = true, ['Hawks'] = true, ['Pidgeons'] = true},
['Elephants'] = true,
['Mythical Beasts'] = {['Dragons'] = true, ['Unicorns'] = true, ['Sea Serpents'] = true, ['Sphinx'] = true, ['Cyclops'] = true,
['Minotaurs'] = true, ['Goblins'] = true, ['Honest Politicians'] = true, ['Ghosts'] = true, ['Scylla and Charybdis'] = true}
},
['Games'] = {'/sc 6_4', true,
['Action'] = true, ['Puzzle'] = true, ['Strategy'] = true, ['Racing'] = true, ['RPG'] = true, ['Obstacle Course'] = true, ['Tycoon'] = true,
['Roblox'] = { ['BrickBattle'] = true, ['Community Building'] = true, ['Roblox Minigames'] = true, ['Contest Place'] = true},
['Board games'] = { ['Chess'] = true, ['Checkers'] = true, ['Settlers of Catan'] = true, ['Tigris and Euphrates'] = true, ['El Grande'] = true,
['Stratego'] = true, ['Carcassonne'] = true}
},
['Sports'] = {'/sc 6_5', true, ['Hockey'] = true, ['Soccer'] = true, ['Football'] = true, ['Baseball'] = true, ['Basketball'] = true,
['Volleyball'] = true, ['Tennis'] = true, ['Sports team practice'] = true,
['Watersports'] = { ['Surfing'] = true,['Swimming'] = true, ['Water Polo'] = true},
['Winter sports'] = { ['Skiing'] = true, ['Snowboarding'] = true, ['Sledding'] = true, ['Skating'] = true},
['Adventure'] = {['Rock climbing'] = true, ['Hiking'] = true, ['Fishing'] = true, ['Horseback riding'] = true},
['Wacky'] = {['Foosball'] = true, ['Calvinball'] = true, ['Croquet'] = true, ['Cricket'] = true, ['Dodgeball'] = true,
['Squash'] = true, ['Trampoline'] = true}
},
['Movies/TV'] = {'/sc 6_6', true, ['Science Fiction'] = true, ['Animated'] = {['Anime'] = true}, ['Comedy'] = true, ['Romantic'] = true,
['Action'] = true, ['Fantasy'] = true},
['Music'] = {'/sc 6_7', true, ['Country'] = true, ['Jazz'] = true, ['Rap'] = true, ['Hip-hop'] = true, ['Techno'] = true, ['Classical'] = true,
['Pop'] = true, ['Rock'] = true},
['Hobbies'] = {'/sc 6_8', true,
['Computers'] = { ['Building computers'] = true, ['Videogames'] = true, ['Coding'] = true, ['Hacking'] = true},
['The Internet'] = { ['lol. teh internets!'] = true, ['Watching vids'] = true},
['Dance'] = true, ['Gymnastics'] = true, ['Listening to music'] = true, ['Arts and crafts'] = true,
['Martial Arts'] = {['Karate'] = true, ['Judo'] = true, ['Taikwon Do'] = true, ['Wushu'] = true, ['Street fighting'] = true},
['Music lessons'] = {['Playing in my band'] = true, ['Playing piano'] = true, ['Playing guitar'] = true,
['Playing violin'] = true, ['Playing drums'] = true, ['Playing a weird instrument'] = true}
},
['Location'] = {'/sc 6_9', true,
['USA'] = {
['West'] = { ['Alaska'] = true, ['Arizona'] = true, ['California'] = true, ['Colorado'] = true, ['Hawaii'] = true,
['Idaho'] = true, ['Montana'] = true, ['Nevada'] = true, ['New Mexico'] = true, ['Oregon'] = true,
['Utah'] = true, ['Washington'] = true, ['Wyoming'] = true
},
['South'] = { ['Alabama'] = true, ['Arkansas'] = true, ['Florida'] = true, ['Georgia'] = true, ['Kentucky'] = true,
['Louisiana'] = true, ['Mississippi'] = true, ['North Carolina'] = true, ['Oklahoma'] = true,
['South Carolina'] = true, ['Tennessee'] = true, ['Texas'] = true, ['Virginia'] = true, ['West Virginia'] = true
},
['Northeast'] = {['Connecticut'] = true, ['Delaware'] = true, ['Maine'] = true, ['Maryland'] = true, ['Massachusetts'] = true,
['New Hampshire'] = true, ['New Jersey'] = true, ['New York'] = true, ['Pennsylvania'] = true, ['Rhode Island'] = true,
['Vermont'] = true
},
['Midwest'] = {['Illinois'] = true, ['Indiana'] = true, ['Iowa'] = true, ['Kansas'] = true, ['Michigan'] = true, ['Minnesota'] = true,
['Missouri'] = true, ['Nebraska'] = true, ['North Dakota'] = true, ['Ohio'] = true, ['South Dakota'] = true, ['Wisconsin'] = true}
},
['Canada'] = {['Alberta'] = true, ['British Columbia'] = true, ['Manitoba'] = true, ['New Brunswick'] = true, ['Newfoundland'] = true,
['Northwest Territories'] = true, ['Nova Scotia'] = true, ['Nunavut'] = true, ['Ontario'] = true, ['Prince Edward Island'] = true,
['Quebec'] = true, ['Saskatchewan'] = true, ['Yukon'] = true},
['Mexico'] = true,
['Central America'] = true,
['Europe'] = {['France'] = true, ['Germany'] = true, ['Spain'] = true, ['Italy'] = true, ['Poland'] = true, ['Switzerland'] = true,
['Greece'] = true, ['Romania'] = true, ['Netherlands'] = true,
['Great Britain'] = {['England'] = true, ['Scotland'] = true, ['Wales'] = true, ['Northern Ireland'] = true}
},
['Asia'] = { ['China'] = true, ['India'] = true, ['Japan'] = true, ['Korea'] = true, ['Russia'] = true, ['Vietnam'] = true},
['South America'] = { ['Argentina'] = true, ['Brazil'] = true},
['Africa'] = { ['Eygpt'] = true, ['Swaziland'] = true},
['Australia'] = true, ['Middle East'] = true, ['Antarctica'] = true, ['New Zealand'] = true
},
['Age'] = {'/sc 6_10', true, ['Rugrat'] = true, ['Kid'] = true, ['Tween'] = true, ['Teen'] = true, ['Twenties'] = true,
['Old'] = true, ['Ancient'] = true, ['Mesozoic'] = true, ['I don\'t want to say my age. Don\'t ask.'] = true},
['Mood'] = {'/sc 6_11', true, ['Good'] = true, ['Great!'] = true, ['Not bad'] = true, ['Sad'] = true, ['Hyper'] = true,
['Chill'] = true, ['Happy'] = true, ['Kind of mad'] = true},
['Boy'] = {'/sc 6_12', true},
['Girl'] = {'/sc 6_13', true},
['I don\'t want to say boy or girl. Don\'t ask.'] = {'/sc 6_14', true},
[1] = '/sc 6'
},
['Game'] = {
['Let\'s build'] = {'/sc 7_0', true},
['Let\'s battle'] = {'/sc 7_1', true},
['Nice one!'] = {'/sc 7_2', true},
['So far so good'] = {'/sc 7_3', true},
['Lucky shot!'] = {'/sc 7_4', true},
['Oh man!'] = {'/sc 7_5', true},
['I challenge you to a fight!'] = {'/sc 7_6', true},
['Help me with this'] = {'/sc 7_7', true},
['Let\'s go to your game'] = {'/sc 7_8', true},
['Can you show me how do to that?'] = {'/sc 7_9', true},
['Backflip!'] = {'/sc 7_10', true},
['Frontflip!'] = {'/sc 7_11', true},
['Dance!'] = {'/sc 7_12', true},
['I\'m on your side!'] = {'/sc 7_13', true},
['Game Commands'] = {'/sc 7_14', true, ['regen'] = true, ['reset'] = true, ['go'] = true, ['fix'] = true, ['respawn'] = true},
[1] = '/sc 7'
};
['Silly'] = {
['Muahahahaha!'] = true,
['all your base are belong to me!'] = true,
['GET OFF MAH LAWN'] = true,
['TEH EPIK DUCK IS COMING!!!'] = true,
['ROFL'] = true,
['1337'] = {true, ['i r teh pwnz0r!'] = true, ['w00t!'] = true, ['z0mg h4x!'] = true, ['ub3rR0xXorzage!'] = true}
},
['Yes'] = {
['Absolutely!'] = true,
['Rock on!'] = true,
['Totally!'] = true,
['Juice!'] = true,
['Yay!'] = true,
['Yesh'] = true
},
['No'] = {
['Ummm. No.'] = true,
['...'] = true,
['Stop!'] = true,
['Go away!'] = true,
['Don\'t do that'] = true,
['Stop breaking the rules'] = true,
['I don\'t want to'] = true
},
['Ok'] = {
['Well... ok'] = true,
['Sure'] = true
},
['Uncertain'] = {
['Maybe'] = true,
['I don\'t know'] = true,
['idk'] = true,
['I can\'t decide'] = true,
['Hmm...'] = true
},
[':-)'] = {
[':-('] = true,
[':D'] = true,
[':-O'] = true,
['lol'] = true,
['=D'] = true,
['D='] = true,
['XD'] = true,
[';D'] = true,
[';)'] = true,
['O_O'] = true,
['=)'] = true,
['@_@'] = true,
['>_<'] = true,
['T_T'] = true,
['^_^'] = true,
['<(0_0<) <(0_0)> (>0_0)> KIRBY DANCE'] = true,
[')\';'] = true,
[':3'] = true
},
['Ratings'] = {
['Rate it!'] = true,
['I give it a 1 out of 10'] = true,
['I give it a 2 out of 10'] = true,
['I give it a 3 out of 10'] = true,
['I give it a 4 out of 10'] = true,
['I give it a 5 out of 10'] = true,
['I give it a 6 out of 10'] = true,
['I give it a 7 out of 10'] = true,
['I give it a 8 out of 10'] = true,
['I give it a 9 out of 10'] = true,
['I give it a 10 out of 10!'] = true,
}
},
CreateEnum('SafeChat'){'Level1', 'Level2', 'Level3'},
SafeChatTree = {},
TempSpaceLabel = nil
}
---------------------------------------------------
local function GetNameValue(pName)
local value = 0
for index = 1, #pName do
local cValue = string.byte(string.sub(pName, index, index))
local reverseIndex = #pName - index + 1
if #pName%2 == 1 then
reverseIndex = reverseIndex - 1
end
if reverseIndex%4 >= 2 then
cValue = -cValue
end
value = value + cValue
end
return value%8
end
function Chat:ComputeChatColor(pName)
return self.ChatColors[GetNameValue(pName) + 1].Color
end
-- This is context based scrolling
function Chat:EnableScrolling(toggle)
-- Genius idea gone to fail, if we switch the camera type we can effectively lock the
-- camera and do no click scrolling
self.MouseOnFrame = false
if self.RenderFrame then
self.RenderFrame.MouseEnter:connect(function()
local character = Player.Character
local torso = WaitForChild(character, 'Torso')
local humanoid = WaitForChild(character, 'Humanoid')
local head = WaitForChild(character, 'Head')
if toggle then
self.MouseOnFrame = true
Camera.CameraType = 'Scriptable'
-- Get relative position of camera and keep to it
Spawn(function()
local currentRelativePos = Camera.CoordinateFrame.p - torso.Position
while Chat.MouseOnFrame do
Camera.CoordinateFrame = CFrame.new(torso.Position + currentRelativePos, head.Position)
wait(0.015)
end
end)
end
end)
self.RenderFrame.MouseLeave:connect(function()
Camera.CameraType = 'Custom'
self.MouseOnFrame = false
end)
end
end
-- TODO: Scrolling using Mouse wheel
function Chat:OnScroll(speed)
if self.MouseOnFrame then
--
end
end
-- Check if we are running on a touch device
function Chat:IsTouchDevice()
local touchEnabled = false
pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end)
return touchEnabled
end
-- Scrolling
function Chat:ScrollQueue(value)
--[[for i = 1, #self.MessageQueue do
if self.MessageQueue[i] then
for _, label in pairs(self.MessageQueue[i]) do
local next = self.MessageQueue[i].Next
local previous = self.MessageQueue[i].Previous
if label and label:IsA('TextLabel') or label:IsA('TextButton') then
if value > 0 and previous and previous['Message'] then
label.Position = previous['Message'].Position
elseif value < 1 and next['Message'] then
label.Position = previous['Message'].Position
end
end
end
end
end ]]
end
-- Handles the rendering of the text objects in their appropriate places
function Chat:UpdateQueue(field, diff)
-- Have to do some sort of correction here
for i = #self.MessageQueue, 1, -1 do
if self.MessageQueue[i] then
for _, label in pairs(self.MessageQueue[i]) do
if label and type(label) ~= 'table' and type(label) ~= 'number' then
if label:IsA('TextLabel') or label:IsA('TextButton') then
if diff then
label.Position = label.Position - UDim2.new(0, 0, diff, 0)
else
if field == self.MessageQueue[i] then
label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale , 0)
-- Just to show up popping effect for the latest message in chat
Spawn(function()
wait(0.05)
while label.TextTransparency >= 0 do
label.TextTransparency = label.TextTransparency - 0.2
wait(0.03)
end
if label == field['Message'] then
label.TextStrokeTransparency = 0.8
else
label.TextStrokeTransparency = 1.0
end
end)
else
label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale, 0)
end
if label.Position.Y.Scale < -0.01 then
-- NOTE: Remove this fix when Textbounds is fixed
label.Visible = false
label:Destroy()
end
end
end
end
end
end
end
end
function Chat:CreateScrollBar()
-- Code for scrolling is in here, partially, but scroll bar drawing isn't drawn
-- TODO: Implement
end
-- For scrolling, to see if we hit the bounds so that we can stop it from scrolling anymore
function Chat:CheckIfInBounds(value)
if #Chat.MessageQueue < 3 then
return true
end
if value > 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale == 0 then
return true
elseif value < 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale < 0 then
return true
else
return false
end
return false
end
-- This is to precompute all playerName space strings
-- This is used to offset the message by exactly this + 2 spacestrings
function Chat:ComputeSpaceString(pLabel)
local nString = " "
if not self.TempSpaceLabel then
self.TempSpaceLabel = Create'TextButton'
{
Size = UDim2.new(0, pLabel.AbsoluteSize.X, 0, pLabel.AbsoluteSize.Y);
FontSize = self.Configuration.FontSize;
Parent = self.RenderFrame;
BackgroundTransparency = 1.0;
Text = nString;
Name = 'SpaceButton'
};
else
self.TempSpaceLabel.Text = nString
end
while self.TempSpaceLabel.TextBounds.X < pLabel.TextBounds.X do
nString = nString .. " "
self.TempSpaceLabel.Text = nString
end
nString = nString .. " "
self.CachedSpaceStrings_List[pLabel.Text] = nString
self.TempSpaceLabel.Text = ""
return nString
end
-- When the playerChatted event fires
-- The message is what the player chatted
function Chat:UpdateChat(cPlayer, message)
local messageField = {
['Player'] = cPlayer,
['Message'] = message
}
if coroutine.status(Chat.MessageThread) == 'dead' then
--Chat.Messages_List = {}
table.insert(Chat.Messages_List, messageField)
Chat.MessageThread = coroutine.create(function()
for i = 1, #Chat.Messages_List do
local field = Chat.Messages_List[i]
Chat:CreateMessage(field['Player'], field['Message'])
end
Chat.Messages_List = {}
end)
coroutine.resume(Chat.MessageThread)
else
table.insert(Chat.Messages_List, messageField)
end
end
function Chat:RecalculateSpacing()
--[[for i = 1, #self.MessageQueue do
local pLabel = self.MessageQueue[i]['Player']
local mLabel = self.MessageQueue[i]['Message']
local prevYScale = mLabel.Size.Y.Scale
local prevText = mLabel.Text
mLabel.Text = prevText
local heightField = mLabel.TextBounds.Y
mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0)
pLabel.Size = mLabel.Size
local diff = mLabel.Size.Y.Scale - prevYScale
Chat:UpdateQueue(self.MessageQueue[i], diff)
end ]]
end
function Chat:ApplyFilter(str)
--[[for _, word in pair(self.Filter_List) do
if string.find(str, word) then
str:gsub(word, '@#$^')
end
end ]]
end
-- NOTE: Temporarily disabled ring buffer to allow for chat to always wrap around
function Chat:CreateMessage(cPlayer, message)
local pName
if not cPlayer then
pName = ''
else
pName = cPlayer.Name
end
message = StringTrim(message)
local pLabel
local mLabel
-- Our history stores upto 50 messages that is 100 textlabels
-- If we ever hit the mark, which would be in every popular game btw
-- we wrap around and reuse the labels
if #self.MessageQueue > self.Configuration.HistoryLength then
--[[pLabel = self.MessageQueue[#self.MessageQueue]['Player']
mLabel = self.MessageQueue[#self.MessageQueue]['Message']
pLabel.Text = pName .. ':'
pLabel.Name = pName
local pColor
if cPlayer.Neutral then
pLabel.TextColor3 = Chat:ComputeChatColor(pName)
else
pLabel.TextColor3 = cPlayer.TeamColor.Color
end
local nString
if not self.CachedSpaceStrings_List[pName] then
nString = Chat:ComputeSpaceString(pLabel)
else
nString = self.CachedSpaceStrings_List[pName]
end
mLabel.Text = ""
mLabel.Name = pName .. " - message"
mLabel.Text = nString .. message;
mLabel.Parent = nil
mLabel.Parent = self.RenderFrame
mLabel.Position = UDim2.new(0, 0, 1, 0);
pLabel.Position = UDim2.new(0, 0, 1, 0);]]
-- Reinserted at the beginning, ring buffer
self.MessageQueue[#self.MessageQueue] = nil
end
--else
-- Haven't hit the mark yet, so keep creating
pLabel = Create'TextLabel'
{
Name = pName;
Text = pName .. ":";
TextColor3 = pColor;
FontSize = Chat.Configuration.FontSize;
TextXAlignment = Enum.TextXAlignment.Left;
TextYAlignment = Enum.TextYAlignment.Top;
Parent = self.RenderFrame;
TextWrapped = false;
Size = UDim2.new(1, 0, 0.1, 0);
BackgroundTransparency = 1.0;
TextTransparency = 1.0;
Position = UDim2.new(0, 0, 1, 0);
BorderSizePixel = 0.0;
TextStrokeColor3 = Color3.new(0.5, 0.5, 0.5);
TextStrokeTransparency = 0.75;
--Active = false;
};
local pColor
if cPlayer.Neutral then
pLabel.TextColor3 = Chat:ComputeChatColor(pName)
else
pLabel.TextColor3 = cPlayer.TeamColor.Color
end
local nString
if not self.CachedSpaceStrings_List[pName] then
nString = Chat:ComputeSpaceString(pLabel)
else
nString = self.CachedSpaceStrings_List[pName]
end
mLabel = Create'TextLabel'
{
Name = pName .. ' - message';
-- Max is 3 lines
Size = UDim2.new(1, 0, 0.5, 0);
TextColor3 = Chat.Configuration.MessageColor;
FontSize = Chat.Configuration.FontSize;
TextXAlignment = Enum.TextXAlignment.Left;
TextYAlignment = Enum.TextYAlignment.Top;
Text = ""; -- this is to stop when the engine reverts the swear words to default, which is button, ugh
Parent = self.RenderFrame;
TextWrapped = true;
BackgroundTransparency = 1.0;
TextTransparency = 1.0;
Position = UDim2.new(0, 0, 1, 0);
BorderSizePixel = 0.0;
TextStrokeColor3 = Color3.new(0, 0, 0);
--TextStrokeTransparency = 0.8;
--Active = false;
};
mLabel.Text = nString .. message;
if not pName then
pLabel.Text = ''
mLabel.TextColor3 = Color3.new(0, 0.4, 1.0)
end
--end
for _, adminName in pairs(self.Admins_List) do
if string.lower(adminName) == string.lower(pName) then
mLabel.TextColor3 = self.Configuration.AdminMessageColor
end
end
pLabel.Visible = true
mLabel.Visible = true
-- This will give beautiful multilines as well
local heightField = mLabel.TextBounds.Y
mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0)
pLabel.Size = mLabel.Size
local yPixels = self.RenderFrame.AbsoluteSize.Y
local yFieldSize = mLabel.TextBounds.Y
local queueField = {}
queueField['Player'] = pLabel
queueField['Message'] = mLabel
queueField['SpawnTime'] = tick() -- Used for identifying when to make the message invisible
table.insert(self.MessageQueue, 1, queueField)
Chat:UpdateQueue(queueField)
end
function Chat:ScreenSizeChanged()
wait()
while self.Frame.AbsoluteSize.Y > 120 do
self.Frame.Size = self.Frame.Size - UDim2.new(0, 0, 0.005, 0)
end
Chat:RecalculateSpacing()
end
function Chat:FindButtonTree(scButton, rootList)
local list = {}
rootList = rootList or self.SafeChatTree
for button, _ in pairs(rootList) do
if button == scButton then
list = rootList[button]
elseif type(rootList[button]) == 'table' then
list = Chat:FindButtonTree(scButton, rootList[button])
end
end
return list
end
function Chat:ToggleSafeChatMenu(scButton)
local list = Chat:FindButtonTree(scButton, self.SafeChatTree)
if list then
for button, _ in pairs(list) do
if button:IsA('TextButton') or button:IsA('ImageButton') then
button.Visible = not button.Visible
end
end
return true
end
return false
end
function Chat:CreateSafeChatOptions(list, rootButton)
local text_List = {}
level = level or 0
local count = 0
text_List[rootButton] = {}
text_List[rootButton][1] = list[1]
rootButton = rootButton or self.SafeChatButton
for msg, _ in pairs(list) do
if type(msg) == 'string' then
local chatText = Create'TextButton'
{
Name = msg;
Text = msg;
Size = UDim2.new(0, 100, 0, 20);
TextXAlignment = Enum.TextXAlignment.Center;
TextColor3 = Color3.new(0.2, 0.1, 0.1);
BackgroundTransparency = 0.5;
BackgroundColor3 = Color3.new(1, 1, 1);
Parent = self.SafeChatFrame;
Visible = false;
Position = UDim2.new(0, rootButton.Position.X.Scale + 105, 0, rootButton.Position.Y.Scale - ((count - 3) * 100));
};
count = count + 1
if type(list[msg]) == 'table' then
text_List[rootButton][chatText] = Chat:CreateSafeChatOptions(list[msg], chatText)
else
--table.insert(text_List[chatText], true)
end
chatText.MouseEnter:connect(function()
Chat:ToggleSafeChatMenu(chatText)
end)
chatText.MouseLeave:connect(function()
Chat:ToggleSafeChatMenu(chatText)
end)
chatText.MouseButton1Click:connect(function()
local lList = Chat:FindButtonTree(chatText)
if lList then
for i, v in pairs(lList) do
end
else
end
pcall(function() PlayersService:Chat(lList[1]) end)
end)
end
end
return text_List
end
function Chat:CreateSafeChatGui()
self.SafeChatFrame = Create'Frame'
{
Name = 'SafeChatFrame';
Size = UDim2.new(1, 0, 1, 0);
Parent = self.Gui;
BackgroundTransparency = 1.0;
Create'ImageButton'
{
Name = 'SafeChatButton';
Size = UDim2.new(0, 44, 0, 31);
Position = UDim2.new(0, 1, 0.35, 0);
BackgroundTransparency = 1.0;
Image = 'http://www.roblox.com/asset/?id=97080365';
};
}
self.SafeChatButton = self.SafeChatFrame.SafeChatButton
-- safe chat button is the root of this tree
self.SafeChatTree[self.SafeChatButton] = Chat:CreateSafeChatOptions(self.SafeChat_List, self.SafeChatButton)
self.SafeChatButton.MouseButton1Click:connect(function()
Chat:ToggleSafeChatMenu(self.SafeChatButton)
end)
end
function Chat:FocusOnChatBar()
if self.ClickToChatButton then
self.ClickToChatButton.Visible = false
end
self.GotFocus = true
if self.Frame['Background'] then
self.Frame.Background.Visible = false
end
self.ChatBar:CaptureFocus()
end
-- For touch devices we create a button instead
function Chat:CreateTouchButton()
self.ChatTouchFrame = Create'Frame'
{
Name = 'ChatTouchFrame';
Size = UDim2.new(0, 128, 0, 32);
Position = UDim2.new(0, 88, 0, 0);
BackgroundTransparency = 1.0;
Parent = self.Gui;
Create'ImageButton'
{
Name = 'ChatLabel';
Size = UDim2.new(0, 74, 0, 28);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
ZIndex = 2.0;
};
Create'ImageLabel'
{
Name = 'Background';
Size = UDim2.new(1, 0, 1, 0);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
Image = 'http://www.roblox.com/asset/?id=97078724'
};
}
self.TapToChatLabel = self.ChatTouchFrame.ChatLabel
self.TouchLabelBackground = self.ChatTouchFrame.Background
self.ChatBar = Create'TextBox'
{
Name = 'ChatBar';
Size = UDim2.new(1, 0, 0.2, 0);
Position = UDim2.new(0, 0, 0.8, 800);
Text = "";
ZIndex = 1.0;
BackgroundTransparency = 1.0;
Parent = self.Frame;
TextXAlignment = Enum.TextXAlignment.Left;
TextColor3 = Color3.new(1, 1, 1);
ClearTextOnFocus = false;
};
self.TapToChatLabel.MouseButton1Click:connect(function()
self.TapToChatLabel.Visible = false
--self.ChatBar.Visible = true
--self.Frame.Background.Visible = true
self.ChatBar:CaptureFocus()
self.GotFocus = true
if self.TouchLabelBackground then
self.TouchLabelBackground.Visible = false
end
end)
end
-- Non touch devices, create the bottom chat bar
function Chat:CreateChatBar()
-- okay now we do
local status, result = pcall(function() return GuiService.UseLuaChat end)
if status and result then
self.ClickToChatButton = Create'TextButton'
{
Name = 'ClickToChat';
Size = UDim2.new(1, 0, 0, 20);
BackgroundTransparency = 1.0;
ZIndex = 2.0;
Parent = self.Gui;
Text = "To chat click here or press \"/\" key";
TextColor3 = Color3.new(1, 1, 0.9);
Position = UDim2.new(0, 0, 1, 0);
TextXAlignment = Enum.TextXAlignment.Left;
FontSize = Enum.FontSize.Size12;
}
self.ChatBar = Create'TextBox'
{
Name = 'ChatBar';
Size = UDim2.new(1, 0, 0, 20);
Position = UDim2.new(0, 0, 1, 0);
Text = "";
ZIndex = 1.0;
BackgroundColor3 = Color3.new(0, 0, 0);
BackgroundTransparency = 0.25;
Parent = self.Gui;
TextXAlignment = Enum.TextXAlignment.Left;
TextColor3 = Color3.new(1, 1, 1);
FontSize = Enum.FontSize.Size12;
ClearTextOnFocus = false;
Text = '';
};
-- Engine has code to offset the entire world, so if we do it by -20 pixels nothing gets in our chat's way
GuiService:SetGlobalSizeOffsetPixel(0, -20)
-- CHatHotKey is '/'
GuiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey)
GuiService.SpecialKeyPressed:connect(function(key)
if key == Enum.SpecialKey.ChatHotkey then
Chat:FocusOnChatBar()
end
end)
self.ClickToChatButton.MouseButton1Click:connect(function()
Chat:FocusOnChatBar()
end)
end
end
-- Create the initial Chat stuff
-- Done only once
function Chat:CreateGui()
self.Gui = script.Parent
self.Frame = Create'Frame'
{
Name = 'ChatFrame';
--Size = self.Configuration.Size;
Size = UDim2.new(0, 500, 0, 120);
Position = UDim2.new(0, 0, 0, 5);
BackgroundTransparency = 1.0;
--ClipsDescendants = true;
ZIndex = 0.0;
Parent = self.Gui;
Active = false;
Create'ImageLabel'
{
Name = 'Background';
Image = 'http://www.roblox.com/asset/?id=97120937'; --96551212';
Size = UDim2.new(1.3, 0, 1.64, 0);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
ZIndex = 0.0;
Visible = false
};
Create'Frame'
{
Name = 'Border';
Size = UDim2.new(1, 0, 0, 1);
Position = UDim2.new(0, 0, 0.8, 0);
BackgroundTransparency = 0.0;
BackgroundColor3 = Color3.new(236/255, 236/255, 236/255);
BorderSizePixel = 0.0;
Visible = false;
};
Create'Frame'
{
Name = 'ChatRenderFrame';
Size = UDim2.new(1.02, 0, 1.01, 0);
Position = UDim2.new(0, 0, 0, 0);
BackgroundTransparency = 1.0;
--ClipsDescendants = true;
ZIndex = 0.0;
Active = false;
};
};
Spawn(function()
wait(0.5)
if IsPhone() then
self.Frame.Size = UDim2.new(0, 280, 0, 120)
end
end)
self.RenderFrame = self.Frame.ChatRenderFrame
if Chat:IsTouchDevice() then
self.Frame.Position = self.Configuration.Position;
self.RenderFrame.Size = UDim2.new(1, 0, 1, 0)
elseif self.Frame.AbsoluteSize.Y > 120 then
Chat:ScreenSizeChanged()
self.Gui.Changed:connect(function(property)
if property == 'AbsoluteSize' then
Chat:ScreenSizeChanged()
end
end)
end
if Player.ChatMode == Enum.ChatMode.TextAndMenu then
if Chat:IsTouchDevice() then
Chat:CreateTouchButton()
else
Chat:CreateChatBar()
--Chat:CreateSafeChatGui()
end
if self.ChatBar then
self.ChatBar.FocusLost:connect(function(enterPressed)
Chat.GotFocus = false
if Chat:IsTouchDevice() then
self.ChatBar.Visible = false
self.TapToChatLabel.Visible = true
if self.TouchLabelBackground then
self.TouchLabelBackground.Visible = true
end
end
if enterPressed and self.ChatBar.Text ~= "" then
local cText = self.ChatBar.Text
if string.sub(self.ChatBar.Text, 1, 1) == '%' then
cText = '(TEAM) ' .. string.sub(cText, 2, #cText)
pcall(function() PlayersService:TeamChat(cText) end)
else
pcall(function() PlayersService:Chat(cText) end)
end
if self.ClickToChatButton then
self.ClickToChatButton.Visible = true
end
self.ChatBar.Text = ""
end
Spawn(function()
wait(5.0)
if not Chat.GotFocus then
Chat.Frame.Background.Visible = false
end
end)
end)
end
end
end
-- Scrolling function
-- Applies a speed(velocity) to have nice scrolling effect
function Input:OnMouseScroll()
Spawn(function()
-- How long should the speed last?
while Input.Speed ~=0 do
if Input.Speed > 1 then
while Input.Speed > 0 do
Input.Speed = Input.Speed - 1
wait(0.25)
end
elseif Input.Speed < 0 then
while Input.Speed < 0 do
Input.Speed = Input.Speed + 1
wait(0.25)
end
end
wait(0.03)
end
end)
if Chat:CheckIfInBounds(Input.Speed) then
return
end
Chat:ScrollQueue()
end
function Input:ApplySpeed(value)
Input.Speed = Input.Speed + value
if not self.Simulating then
Input:OnMouseScroll()
end
end
function Input:Initialize()
self.Mouse.WheelBackward:connect(function()
Input:ApplySpeed(self.Configuration.DefaultSpeed)
end)
self.Mouse.WheelForward:connect(function()
Input:ApplySpeed(self.Configuration.DefaultSpeed)
end)
end
function Chat:FindMessageInSafeChat(message, list)
local foundMessage = false
for msg, _ in pairs(list) do
if msg == message then
return true
end
if type(list[msg]) == 'table' then
foundMessage = Chat:FindMessageInSafeChat(message, list[msg])
if foundMessage then
return true
end
end
end
return foundMessage
end
-- Just a wrapper around our PlayerChatted event
function Chat:PlayerChatted(...)
local args = {...}
local argCount = select('#', ...)
local player
local message
-- This doesn't look very good, but what else to do?
if args[2] then
player = args[2]
end
if args[3] then
message = args[3]
if string.sub(message, 1, 1) == '%' then
message = '(TEAM) ' .. string.sub(message, 2, #message)
end
end
if PlayersService.ClassicChat then
if Player.ChatMode == Enum.ChatMode.TextAndMenu then
Chat:UpdateChat(player, message)
elseif Player.ChatMode == Enum.ChatMode.Menu and string.sub(message, 3) == '/sc' then
Chat:UpdateChat(player, message)
else
if Chat:FindMessageInSafeChat(message, self.SafeChat_List) then
Chat:UpdateChat(player, message)
end
end
end
end
-- After Chat.Configuration.Lifetime seconds of existence, the labels become invisible
-- Runs only every 5 seconds and has to loop through 50 values
-- Shouldn't be too expensive
function Chat:CullThread()
while true do
if #self.MessageQueue > 0 then
for _, field in pairs(self.MessageQueue) do
if field['SpawnTime'] and field['Player'] and field['Message'] and tick() - field['SpawnTime'] > self.Configuration.LifeTime then
field['Player'].Visible = false
field['Message'].Visible = false
end
end
end
wait(5.0)
end
end
-- RobloxLock everything so users can't delete them(?)
function Chat:LockAllFields(gui)
end
-- Constructor
-- This function initializes everything
function Chat:Initialize()
Chat:CreateGui()
self.EventListener = PlayersService.PlayerChatted:connect(function(...)
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat:PlayerChatted(...)
end)
self.MessageThread = coroutine.create(function() end)
coroutine.resume(self.MessageThread)
-- Initialize input for us
Input:Initialize()
-- Eww, everytime a player is added, you have to redo the connection
-- Seems this is not automatic
-- NOTE: PlayerAdded only fires on the server, hence ChildAdded is used here
PlayersService.ChildAdded:connect(function()
Chat.EventListener:disconnect()
self.EventListener = PlayersService.PlayerChatted:connect(function(...)
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat:PlayerChatted(...)
end)
end)
Spawn(function()
Chat:CullThread()
end)
self.Frame.DescendantAdded:connect(function(descendant)
end)
end
Chat:Initialize()