RBXLegacy-src/CoreGui2012.rbxm

3601 lines
112 KiB
Plaintext

<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Script" referent="RBX0">
<Properties>
<bool name="Disabled">false</bool>
<Content name="LinkedSource"><null></null></Content>
<string name="Name">GUI_Copy</string>
<ProtectedString name="Source">script.PlayerList:clone().Parent = game.StarterGui;
script:remove();</ProtectedString>
<bool name="archivable">true</bool>
</Properties>
<Item class="Script" referent="RBX1">
<Properties>
<bool name="Disabled">false</bool>
<Content name="LinkedSource"><null></null></Content>
<string name="Name">PlayerList</string>
<ProtectedString name="Source">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&apos;re already in the world
tryConnect()
return connection
end
local function CreateButtons(frame, buttons, yPos, ySize)
local buttonNum = 1
local buttonObjs = {}
for i, obj in ipairs(buttons) do
local button = Instance.new(&quot;TextButton&quot;)
button.Name = &quot;Button&quot; .. buttonNum
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size18
button.AutoButtonColor = true
button.Style = Enum.ButtonStyle.RobloxButtonDefault
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 &gt;= 3 then
local spacing = .1 / numButtons
local buttonSize = .9 / numButtons
buttonNum = 1
while buttonNum &lt;= 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 &gt; 0.5 then
wholeNum = wholeNum + 1
end
relativePosX = wholeNum/newStep
local result = math.ceil(relativePosX * newStep)
if sliderPosition.Value ~= (result + 1) then --onky update if we moved a step
sliderPosition.Value = result + 1
if relativePosX == 1 then
slider.Position = UDim2.new(1,-slider.AbsoluteSize.X,slider.Position.Y.Scale,slider.Position.Y.Offset)
else
slider.Position = UDim2.new(relativePosX,0,slider.Position.Y.Scale,slider.Position.Y.Offset)
end
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(&quot;Frame&quot;)
frame.Size = UDim2.new(0.5, 0, 0, 165)
frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
frame.Name = &quot;MessageDialog&quot;
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local styleImage = Instance.new(&quot;ImageLabel&quot;)
styleImage.Name = &quot;StyleImage&quot;
styleImage.BackgroundTransparency = 1
styleImage.Position = UDim2.new(0,5,0,15)
if style == &quot;error&quot; or style == &quot;Error&quot; then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = &quot;http://www.roblox.com/asset?id=42565285&quot;
elseif style == &quot;notify&quot; or style == &quot;Notify&quot; then
styleImage.Size = UDim2.new(0, 71, 0, 71)
styleImage.Image = &quot;http://www.roblox.com/asset?id=42604978&quot;
elseif style == &quot;confirm&quot; or style == &quot;Confirm&quot; then
styleImage.Size = UDim2.new(0, 74, 0, 76)
styleImage.Image = &quot;http://www.roblox.com/asset?id=42557901&quot;
else
return t.CreateMessageDialog(title,message,buttons)
end
styleImage.Parent = frame
local titleLabel = Instance.new(&quot;TextLabel&quot;)
titleLabel.Name = &quot;Title&quot;
titleLabel.Text = title
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(&quot;TextLabel&quot;)
messageLabel.Name = &quot;Message&quot;
messageLabel.Text = message
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(&quot;Frame&quot;)
frame.Size = UDim2.new(0.5, 0, 0.5, 0)
frame.Position = UDim2.new(0.25, 0, 0.25, 0)
frame.Name = &quot;MessageDialog&quot;
frame.Active = true
frame.Style = Enum.FrameStyle.RobloxRound
local titleLabel = Instance.new(&quot;TextLabel&quot;)
titleLabel.Name = &quot;Title&quot;
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(&quot;TextLabel&quot;)
messageLabel.Name = &quot;Message&quot;
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)
local width = UDim.new(0, 100)
local height = UDim.new(0, 32)
local xPos = 0.055
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = &quot;DropDownMenu&quot;
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(width, height)
local dropDownMenu = Instance.new(&quot;TextButton&quot;)
dropDownMenu.Name = &quot;DropDownMenuButton&quot;
dropDownMenu.TextWrap = true
dropDownMenu.TextColor3 = Color3.new(1,1,1)
dropDownMenu.Text = &quot;Choose One&quot;
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
dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
dropDownMenu.Size = UDim2.new(1,0,1,0)
dropDownMenu.Parent = frame
dropDownMenu.ZIndex = 2
local dropDownIcon = Instance.new(&quot;ImageLabel&quot;)
dropDownIcon.Name = &quot;Icon&quot;
dropDownIcon.Active = false
dropDownIcon.Image = &quot;http://www.roblox.com/asset/?id=45732894&quot;
dropDownIcon.BackgroundTransparency = 1
dropDownIcon.Size = UDim2.new(0,11,0,6)
dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
dropDownIcon.Parent = dropDownMenu
dropDownIcon.ZIndex = 2
local itemCount = #items
local dropDownItemCount = #items
local useScrollButtons = false
if dropDownItemCount &gt; 6 then
useScrollButtons = true
dropDownItemCount = 6
end
local droppedDownMenu = Instance.new(&quot;TextButton&quot;)
droppedDownMenu.Name = &quot;List&quot;
droppedDownMenu.Text = &quot;&quot;
droppedDownMenu.BackgroundTransparency = 1
--droppedDownMenu.AutoButtonColor = true
droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
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
local choiceButton = Instance.new(&quot;TextButton&quot;)
choiceButton.Name = &quot;ChoiceButton&quot;
choiceButton.BackgroundTransparency = 1
choiceButton.BorderSizePixel = 0
choiceButton.Text = &quot;ReplaceMe&quot;
choiceButton.TextColor3 = Color3.new(1,1,1)
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
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 == &quot;ChoiceButton&quot; then
child.ZIndex = baseZIndex + 2
elseif child.Name == &quot;ClickCaptureButton&quot; then
child.ZIndex = baseZIndex
end
end
end
end
local scrollBarPosition = 1
local updateScroll = function()
if scrollUpButton then
scrollUpButton.Active = scrollBarPosition &gt; 1
end
if scrollDownButton then
scrollDownButton.Active = scrollBarPosition + dropDownItemCount &lt;= 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 == &quot;ChoiceButton&quot; then
if childNum &lt; scrollBarPosition or childNum &gt;= 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 = Color3.new(1,1,1)
obj.BackgroundTransparency = 1
childNum = childNum + 1
end
end
end
local toggleVisibility = function()
dropDownSelected = not dropDownSelected
dropDownMenu.Visible = not dropDownSelected
droppedDownMenu.Visible = dropDownSelected
if dropDownSelected then
setZIndex(4)
else
setZIndex(2)
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 == &quot;ChoiceButton&quot; then
if obj.Text == text then
obj.Font = Enum.Font.ArialBold
foundItem = true
scrollBarPosition = childNum
else
obj.Font = Enum.Font.Arial
end
childNum = childNum + 1
end
end
end
if not text then
dropDownMenu.Text = &quot;Choose One&quot;
scrollBarPosition = 1
else
if not foundItem then
error(&quot;Invalid Selection Update -- &quot; .. text)
end
if scrollBarPosition + dropDownItemCount &gt; itemCount + 1 then
scrollBarPosition = itemCount - dropDownItemCount + 1
end
dropDownMenu.Text = text
end
end
local function scrollDown()
if scrollBarPosition + dropDownItemCount &lt;= itemCount then
scrollBarPosition = scrollBarPosition + 1
updateScroll()
return true
end
return false
end
local function scrollUp()
if scrollBarPosition &gt; 1 then
scrollBarPosition = scrollBarPosition - 1
updateScroll()
return true
end
return false
end
if useScrollButtons then
--Make some scroll buttons
scrollUpButton = Instance.new(&quot;ImageButton&quot;)
scrollUpButton.Name = &quot;ScrollUpButton&quot;
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = &quot;rbxasset://textures/ui/scrollbuttonUp.png&quot;
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(&quot;ImageButton&quot;)
scrollDownButton.Name = &quot;ScrollDownButton&quot;
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = &quot;rbxasset://textures/ui/scrollbuttonDown.png&quot;
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(&quot;ImageLabel&quot;)
scrollbar.Name = &quot;ScrollBar&quot;
scrollbar.Image = &quot;rbxasset://textures/ui/scrollbar.png&quot;
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
button.MouseButton1Click:connect(function()
--Remove Highlight
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundTransparency = 1
updateSelection(item)
onSelect(item)
toggleVisibility()
end)
button.MouseEnter:connect(function()
--Add Highlight
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundTransparency = 0
end)
button.MouseLeave:connect(function()
--Remove Highlight
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundTransparency = 1
end)
end
--This does the initial layout of the buttons
updateScroll()
local bigFakeButton = Instance.new(&quot;TextButton&quot;)
bigFakeButton.BackgroundTransparency = 1
bigFakeButton.Name = &quot;ClickCaptureButton&quot;
bigFakeButton.Size = UDim2.new(0, 4000, 0, 3000)
bigFakeButton.Position = UDim2.new(0, -2000, 0, -1500)
bigFakeButton.ZIndex = 1
bigFakeButton.Text = &quot;&quot;
bigFakeButton.Parent = droppedDownMenu
bigFakeButton.MouseButton1Click:connect(toggleVisibility)
dropDownMenu.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, &quot;Changed&quot;,
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(&quot;Font and FontSize must be non-nil&quot;)
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(&quot;Unknown FontSize&quot;)
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(&quot;Unknown FontSize&quot;)
end
else
error(&quot;Unknown Font &quot; .. 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(&quot;TextLabel&quot;) or child:IsA(&quot;TextButton&quot;) then
local isLabel = child:IsA(&quot;TextLabel&quot;)
if isLabel then
pixelsRemaining = pixelsRemaining - settingsTable[&quot;TextLabelPositionPadY&quot;]
else
pixelsRemaining = pixelsRemaining - settingsTable[&quot;TextButtonPositionPadY&quot;]
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 &lt; 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[&quot;TextLabelSizePadY&quot;])
else
child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable[&quot;TextButtonSizePadY&quot;])
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[&quot;TextLabelPositionPadY&quot;]
else
pixelsRemaining = pixelsRemaining - settingsTable[&quot;TextButtonPositionPadY&quot;]
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 &gt;= 0)
end
end
end
t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
if not frame:IsA(&quot;GuiObject&quot;) then
error(&quot;Frame must be a GuiObject&quot;)
end
for i, child in ipairs(guiObjects) do
if not child:IsA(&quot;GuiObject&quot;) then
error(&quot;All elements that are layed out must be of type GuiObject&quot;)
end
end
if not settingsTable then
settingsTable = {}
end
if not settingsTable[&quot;TextLabelSizePadY&quot;] then
settingsTable[&quot;TextLabelSizePadY&quot;] = 0
end
if not settingsTable[&quot;TextLabelPositionPadY&quot;] then
settingsTable[&quot;TextLabelPositionPadY&quot;] = 0
end
if not settingsTable[&quot;TextButtonSizePadY&quot;] then
settingsTable[&quot;TextButtonSizePadY&quot;] = 12
end
if not settingsTable[&quot;TextButtonPositionPadY&quot;] then
settingsTable[&quot;TextButtonPositionPadY&quot;] = 2
end
--Wrapper frame takes care of styled objects
local wrapperFrame = Instance.new(&quot;Frame&quot;)
wrapperFrame.Name = &quot;WrapperFrame&quot;
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 == &quot;AbsoluteSize&quot; then
--Wait a heartbeat for it to sync in
recalculate()
end
end)
frame.AncestryChanged:connect(recalculate)
layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
end
t.CreateSlider = function(steps,width,position)
local sliderGui = Instance.new(&quot;Frame&quot;)
sliderGui.Size = UDim2.new(1,0,1,0)
sliderGui.BackgroundTransparency = 1
sliderGui.Name = &quot;SliderGui&quot;
local areaSoak = Instance.new(&quot;TextButton&quot;)
areaSoak.Name = &quot;AreaSoak&quot;
areaSoak.Text = &quot;&quot;
areaSoak.BackgroundTransparency = 1
areaSoak.Active = false
areaSoak.Size = UDim2.new(1,0,1,0)
areaSoak.Visible = false
areaSoak.ZIndex = 4
areaSoak.Parent = sliderGui
local sliderPosition = Instance.new(&quot;IntValue&quot;)
sliderPosition.Name = &quot;SliderPosition&quot;
sliderPosition.Value = 0
sliderPosition.Parent = sliderGui
local id = math.random(1,100)
local bar = Instance.new(&quot;Frame&quot;)
bar.Name = &quot;Bar&quot;
bar.BackgroundColor3 = Color3.new(0,0,0)
if type(width) == &quot;number&quot; 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[&quot;X&quot;] and position[&quot;X&quot;][&quot;Scale&quot;] and position[&quot;X&quot;][&quot;Offset&quot;] and position[&quot;Y&quot;] and position[&quot;Y&quot;][&quot;Scale&quot;] and position[&quot;Y&quot;][&quot;Offset&quot;] then
bar.Position = position
end
local slider = Instance.new(&quot;ImageButton&quot;)
slider.Name = &quot;Slider&quot;
slider.BackgroundTransparency = 1
slider.Image = &quot;rbxasset://textures/ui/Slider.png&quot;
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)
local relativePosX = (sliderPosition.Value - 1) / steps
slider.Position = UDim2.new(relativePosX,0,slider.Position.Y.Scale,slider.Position.Y.Offset)
end)
return sliderGui, sliderPosition
end
t.CreateScrollingFrame = function(orderList,scrollStyle)
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = &quot;ScrollingFrame&quot;
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1,0,1,0)
local scrollUpButton = Instance.new(&quot;ImageButton&quot;)
scrollUpButton.Name = &quot;ScrollUpButton&quot;
scrollUpButton.BackgroundTransparency = 1
scrollUpButton.Image = &quot;rbxasset://textures/ui/scrollbuttonUp.png&quot;
scrollUpButton.Size = UDim2.new(0,17,0,17)
local scrollDownButton = Instance.new(&quot;ImageButton&quot;)
scrollDownButton.Name = &quot;ScrollDownButton&quot;
scrollDownButton.BackgroundTransparency = 1
scrollDownButton.Image = &quot;rbxasset://textures/ui/scrollbuttonDown.png&quot;
scrollDownButton.Size = UDim2.new(0,17,0,17)
local style = &quot;simple&quot;
if scrollStyle and tostring(scrollStyle) then
style = scrollStyle
end
local scrollPosition = 1
local rowSize = 1
local layoutGridScrollBar = function()
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(&quot;GuiObject&quot;) then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollPosition = 1
return
end
if scrollPosition &gt; #guiObjects then
scrollPosition = #guiObjects
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
while pixelsBelowScrollbar &lt; totalPixelsY and pos &gt;= 1 do
if pos &gt;= scrollPosition then
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
else
xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
rowSizeCounter = rowSizeCounter + 1
if xCounter &gt;= totalPixelsX then
if setRowSize then
rowSize = rowSizeCounter - 1
setRowSize = false
end
rowSizeCounter = 0
xCounter = 0
if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y &lt;= totalPixelsY then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
if scrollPosition &lt;= rowSize then
scrollPosition = rowSize
break
else
--print(&quot;Backing up ScrollPosition from -- &quot; ..scrollPosition)
scrollPosition = scrollPosition - rowSize
end
else
break
end
end
end
pos = pos - 1
end
xCounter = 0
--print(&quot;ScrollPosition = &quot; .. scrollPosition)
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 &lt; scrollPosition then
--print(&quot;Hiding &quot; .. child.Name)
child.Visible = false
else
if pixelsRemainingY &lt; 0 then
--print(&quot;Out of Space &quot; .. child.Name)
child.Visible = false
else
--print(&quot;Laying out &quot; .. child.Name)
--GuiObject
if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
if xCounter + child.AbsoluteSize.X &gt;= 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) &gt;= 0)
lastChildSize = child.AbsoluteSize
end
end
end
scrollUpButton.Active = (scrollPosition &gt; 1)
if lastChildSize == 0 then
scrollDownButton.Active = false
else
scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) &lt; 0)
end
end
local layoutSimpleScrollBar = function()
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(&quot;GuiObject&quot;) then
table.insert(guiObjects, child)
end
end
end
end
if #guiObjects == 0 then
scrollUpButton.Active = false
scrollDownButton.Active = false
scrollPosition = 1
return
end
if scrollPosition &gt; #guiObjects then
scrollPosition = #guiObjects
end
local totalPixels = frame.AbsoluteSize.Y
local pixelsRemaining = frame.AbsoluteSize.Y
local pixelsBelowScrollbar = 0
local pos = #guiObjects
while pixelsBelowScrollbar &lt; totalPixels and pos &gt;= 1 do
if pos &gt;= scrollPosition then
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
else
if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y &lt;= totalPixels then
--It fits, so back up our scroll position
pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
if scrollPosition &lt;= 1 then
scrollPosition = 1
break
else
--print(&quot;Backing up ScrollPosition from -- &quot; ..scrollPosition)
scrollPosition = scrollPosition - 1
end
else
break
end
end
pos = pos - 1
end
--print(&quot;ScrollPosition = &quot; .. scrollPosition)
pos = scrollPosition
for i, child in ipairs(guiObjects) do
if i &lt; scrollPosition then
--print(&quot;Hiding &quot; .. child.Name)
child.Visible = false
else
if pixelsRemaining &lt; 0 then
--print(&quot;Out of Space &quot; .. child.Name)
child.Visible = false
else
--print(&quot;Laying out &quot; .. child.Name)
--GuiObject
child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
child.Visible = (pixelsRemaining &gt;= 0)
end
end
end
scrollUpButton.Active = (scrollPosition &gt; 1)
scrollDownButton.Active = (pixelsRemaining &lt; 0)
end
local reentrancyGuard = false
local recalculate = function()
if reentrancyGuard then
return
end
reentrancyGuard = true
wait()
local success, err = nil
if style == &quot;grid&quot; then
success, err = pcall(function() layoutGridScrollBar(frame) end)
elseif style == &quot;simple&quot; then
success, err = pcall(function() layoutSimpleScrollBar(frame) end)
end
if not success then print(err) end
reentrancyGuard = false
end
local scrollUp = function()
if scrollUpButton.Active then
scrollPosition = scrollPosition - rowSize
recalculate()
end
end
local scrollDown = function()
if scrollDownButton.Active then
scrollPosition = scrollPosition + rowSize
recalculate()
end
end
local scrollMouseCount = 0
scrollUpButton.MouseButton1Click:connect(
function()
--print(&quot;Up-MouseButton1Click&quot;)
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseLeave:connect(
function()
--print(&quot;Up-Leave&quot;)
scrollMouseCount = scrollMouseCount + 1
end)
scrollUpButton.MouseButton1Down:connect(
function()
--print(&quot;Up-Down&quot;)
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)
scrollDownButton.MouseButton1Click:connect(
function()
--print(&quot;Down-Click&quot;)
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseLeave:connect(
function()
--print(&quot;Down-Leave&quot;)
scrollMouseCount = scrollMouseCount + 1
end)
scrollDownButton.MouseButton1Down:connect(
function()
--print(&quot;Down-Down&quot;)
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)
frame.ChildAdded:connect(function()
recalculate()
end)
frame.ChildRemoved:connect(function()
recalculate()
end)
frame.Changed:connect(
function(prop)
if prop == &quot;AbsoluteSize&quot; then
--Wait a heartbeat for it to sync in
recalculate()
end
end)
frame.AncestryChanged:connect(recalculate)
return frame, scrollUpButton, scrollDownButton, recalculate
end
local function binaryGrow(min, max, fits)
if min &gt; max then
return min
end
local biggestLegal = min
while min &lt;= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (biggestLegal == nil or biggestLegal &lt; mid) then
biggestLegal = mid
--Try growing
min = mid + 1
else
--Doesn&apos;t fit, shrink
max = mid - 1
end
end
return biggestLegal
end
local function binaryShrink(min, max, fits)
if min &gt; max then
return min
end
local smallestLegal = max
while min &lt;= max do
local mid = min + math.floor((max - min) / 2)
if fits(mid) and (smallestLegal == nil or smallestLegal &gt; mid) then
smallestLegal = mid
--It fits, shrink
max = mid - 1
else
--Doesn&apos;t fit, grow
min = mid + 1
end
end
return smallestLegal
end
local function getGuiOwner(instance)
while instance ~= nil do
if instance:IsA(&quot;ScreenGui&quot;) or instance:IsA(&quot;BillboardGui&quot;) 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 = &quot;Full&quot; .. 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 .. &quot;~&quot;
--Shrink the text
local textSize = binaryGrow(0, len,
function(pos)
if pos == 0 then
textLabel.Text = &quot;~&quot;
else
textLabel.Text = string.sub(text, 1, pos) .. &quot;~&quot;
end
return textLabel.TextFits
end)
shortText = string.sub(text, 1, textSize) .. &quot;~&quot;
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 = &quot;&quot;
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 == &quot;AbsoluteSize&quot; 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(&quot;Frame&quot;)
frame.Name = &quot;Tutorial-&quot; .. 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(&quot;Frame&quot;)
transitionFrame.Name = &quot;TransitionFrame&quot;
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(&quot;ObjectValue&quot;)
currentPageValue.Name = &quot;CurrentTutorialPage&quot;
currentPageValue.Value = nil
currentPageValue.Parent = frame
local boolValue = Instance.new(&quot;BoolValue&quot;)
boolValue.Name = &quot;Buttons&quot;
boolValue.Value = createButtons
boolValue.Parent = frame
local pages = Instance.new(&quot;Frame&quot;)
pages.Name = &quot;Pages&quot;
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(&quot;Showing tutorial-&quot;,tutorialKey)
local currentTutorialPage = getVisiblePageAndHideOthers()
local firstPage = pages:FindFirstChild(&quot;TutorialPage1&quot;)
if firstPage then
TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
else
error(&quot;Could not find TutorialPage1&quot;)
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(&quot;TutorialPage&quot; .. pageNum)
local currentTutorialPage = getVisiblePageAndHideOthers()
TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
end
return frame, showTutorial, dismissTutorial, gotoPage
end
local function CreateBasicTutorialPage(name, handleResize, skipTutorial)
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = &quot;TutorialPage&quot;
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(&quot;TextLabel&quot;)
frameHeader.Name = &quot;Header&quot;
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(&quot;ImageButton&quot;)
skipButton.Name = &quot;SkipButton&quot;
skipButton.AutoButtonColor = false
skipButton.BackgroundTransparency = 1
skipButton.Image = &quot;http://www.roblox.com/asset/?id=37813546&quot;
skipButton.MouseButton1Click:connect(function()
skipButton.Image = &quot;http://www.roblox.com/asset/?id=37813546&quot;
skipTutorial()
end)
skipButton.MouseEnter:connect(function()
skipButton.Image = &quot;http://www.roblox.com/asset/?id=37813556&quot;
end)
skipButton.MouseLeave:connect(function()
skipButton.Image = &quot;http://www.roblox.com/asset/?id=37813546&quot;
end)
skipButton.Size = UDim2.new(0, 55, 0, 22)
skipButton.Position = UDim2.new(1, -55, 0, 0)
skipButton.Parent = frame
local innerFrame = Instance.new(&quot;Frame&quot;)
innerFrame.Name = &quot;ContentFrame&quot;
innerFrame.BackgroundTransparency = 1
innerFrame.Position = UDim2.new(0,0,0,22)
innerFrame.Parent = frame
local nextButton = Instance.new(&quot;TextButton&quot;)
nextButton.Name = &quot;NextButton&quot;
nextButton.Text = &quot;Next&quot;
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(&quot;TextButton&quot;)
prevButton.Name = &quot;PrevButton&quot;
prevButton.Text = &quot;Previous&quot;
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
innerFrame.Size = UDim2.new(1,0,1,-22-35)
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 == &quot;Parent&quot; then
if parentConnection ~= nil then
parentConnection:disconnect()
parentConnection = nil
end
if frame.Parent and frame.Parent:IsA(&quot;GuiObject&quot;) then
parentConnection = frame.Parent.Changed:connect(
function(parentProp)
if parentProp == &quot;AbsoluteSize&quot; then
wait()
basicHandleResize()
end
end)
basicHandleResize()
end
end
if prop == &quot;Visible&quot; then
basicHandleResize()
end
end)
return frame, innerFrame
end
t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
local frame = nil
local contentFrame = nil
local textLabel = Instance.new(&quot;TextLabel&quot;)
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)
local frame = nil
local contentFrame = nil
local imageLabel = Instance.new(&quot;ImageLabel&quot;)
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 &gt;= x and size &gt;= y
end)
if size &gt;= x and size &gt;= 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 &gt; 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
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)
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.ContentFrame.Size = UDim2.new(1,0,1,-22)
tutorialPage.NextButton.Parent = nil
tutorialPage.PrevButton.Parent = nil
end
local children = tutorial.Pages:GetChildren()
if children and #children &gt; 0 then
tutorialPage.Name = &quot;TutorialPage&quot; .. (#children+1)
local previousPage = children[#children]
if not previousPage:IsA(&quot;GuiObject&quot;) then
error(&quot;All elements under Pages must be GuiObjects&quot;)
end
if tutorial.Buttons.Value then
if previousPage.NextButton.Active then
error(&quot;NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function&quot;)
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(&quot;PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function&quot;)
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 = &quot;TutorialPage1&quot;
tutorialPage.Parent = tutorial.Pages
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 == &quot;CreatePropertyDropDownMenu&quot; or funcNameOrFunc == t.CreatePropertyDropDownMenu then
return &quot;Function CreatePropertyDropDownMenu. &quot; ..
&quot;Arguments: (instance, propertyName, enumType). &quot; ..
&quot;Side effect: returns a container with a drop-down-box that is linked to the &apos;property&apos; field of &apos;instance&apos; which is of type &apos;enumType&apos;&quot;
end
if funcNameOrFunc == &quot;CreateDropDownMenu&quot; or funcNameOrFunc == t.CreateDropDownMenu then
return &quot;Function CreateDropDownMenu. &quot; ..
&quot;Arguments: (items, onItemSelected). &quot; ..
&quot;Side effect: Returns 2 results, a container to the gui object and a &apos;updateSelection&apos; function for external updating. The container is a drop-down-box created around a list of items&quot;
end
if funcNameOrFunc == &quot;CreateMessageDialog&quot; or funcNameOrFunc == t.CreateMessageDialog then
return &quot;Function CreateMessageDialog. &quot; ..
&quot;Arguments: (title, message, buttons). &quot; ..
&quot;Side effect: Returns a gui object of a message box with &apos;title&apos; and &apos;message&apos; as passed in. &apos;buttons&apos; input is an array of Tables contains a &apos;Text&apos; and &apos;Function&apos; field for the text/callback of each button&quot;
end
if funcNameOrFunc == &quot;CreateStyledMessageDialog&quot; or funcNameOrFunc == t.CreateStyledMessageDialog then
return &quot;Function CreateStyledMessageDialog. &quot; ..
&quot;Arguments: (title, message, style, buttons). &quot; ..
&quot;Side effect: Returns a gui object of a message box with &apos;title&apos; and &apos;message&apos; as passed in. &apos;buttons&apos; input is an array of Tables contains a &apos;Text&apos; and &apos;Function&apos; field for the text/callback of each button, &apos;style&apos; is a string, either Error, Notify or Confirm&quot;
end
if funcNameOrFunc == &quot;GetFontHeight&quot; or funcNameOrFunc == t.GetFontHeight then
return &quot;Function GetFontHeight. &quot; ..
&quot;Arguments: (font, fontSize). &quot; ..
&quot;Side effect: returns the size in pixels of the given font + fontSize&quot;
end
if funcNameOrFunc == &quot;LayoutGuiObjects&quot; or funcNameOrFunc == t.LayoutGuiObjects then
end
if funcNameOrFunc == &quot;CreateScrollingFrame&quot; or funcNameOrFunc == t.CreateScrollingFrame then
return &quot;Function CreateScrollingFrame. &quot; ..
&quot;Arguments: (orderList, style) &quot; ..
&quot;Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). &apos;scrollFrame&apos; 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 &apos;grid&apos; styling if style is passed &apos;grid&apos; as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)&quot;
end
if funcNameOrFunc == &quot;AutoTruncateTextObject&quot; or funcNameOrFunc == t.AutoTruncateTextObject then
return &quot;Function AutoTruncateTextObject. &quot; ..
&quot;Arguments: (textLabel) &quot; ..
&quot;Side effect: returns 2 objects, (textLabel, changeText). The &apos;textLabel&apos; input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. &apos;changeText&apos; is a function that can be used to change the text, it takes 1 string as an argument&quot;
end
if funcNameOrFunc == &quot;CreateSlider&quot; or funcNameOrFunc == t.CreateSlider then
return &quot;Function CreateSlider. &quot; ..
&quot;Arguments: (steps, width, position) &quot; ..
&quot;Side effect: returns 2 objects, (sliderGui, sliderPosition). The &apos;steps&apos; argument specifies how many different positions the slider can hold along the bar. &apos;width&apos; specifies in pixels how wide the bar should be (modifiable afterwards if desired). &apos;position&apos; argument should be a UDim2 for slider positioning. &apos;sliderPosition&apos; is an IntValue whose current .Value specifies the specific step the slider is currently on.&quot;
end
end
local NewPlayerListGui = Instance.new(&quot;ScreenGui&quot;,script.Parent)
NewPlayerListGui.Name = &quot;NewPlayerList&quot;
coroutine.resume(coroutine.create(function()
NewPlayerListGui.Parent = game.CoreGui
if game.CoreGui:FindFirstChild(&quot;NewPlayerList&quot;) then
game.CoreGui[&quot;NewPlayerList&quot;].Parent = nil
end end))
local localTesting = true
local friendWord = &quot;Friend&quot;
local friendWordLowercase = &quot;friend&quot;
local testFriendingPlaces = {}
testFriendingPlaces[41324860] = true
local enableFriendingGlobally = false
local testPlayerListPlaces = {}
testPlayerListPlaces[41324860] = true
testPlayerListPlaces[10042455] = true
local enablePlayerListGlobally = false
local bigEasingStyle = Enum.EasingStyle.Back
local smallEasingStyle = Enum.EasingStyle.Quart
local lightBackground = true
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, prop)
while not instance[prop] do
instance.Changed:wait()
end
end
local function Color3I(r,g,b)
return Color3.new(r/255,g/255,b/255)
end
function robloxLock(instance)
end
function ArrayRemove(t, obj)
for i, obj2 in ipairs(t) do
if obj == obj2 then
table.remove(t, i)
return true
end
end
return false
end
local function getPlayers()
local result = {}
local players = game:GetService(&quot;Players&quot;):GetChildren()
if players then
for i, player in ipairs(players) do
if player:IsA(&quot;Player&quot;) then
table.insert(result, player)
end
end
end
return result
end
local brickColorTable = {}
for i = 0, 63 do
brickColorTable[BrickColor.palette(i).Name] = BrickColor.palette(i).Color
end
local function remapColor(i, j)
brickColorTable[BrickColor.palette(i).Name] = BrickColor.palette(j).Color
end
remapColor(13, 12)
remapColor(14, 12)
remapColor(15, 12)
remapColor(61, 29)
remapColor(63, 62)
remapColor(56, 50)
remapColor(45, 53)
remapColor(51, 20)
remapColor(4, 20)
remapColor(59, 35)
remapColor(60, 29)
local function getColor(brickColor)
if brickColorTable[brickColor.Name] then
return brickColorTable[brickColor.Name]
else
return brickColor.Color;
end
end
local function getTeams()
local result = {}
local teams = game:GetService(&quot;Teams&quot;):GetChildren()
for i, team in ipairs(teams) do
if team:IsA(&quot;Team&quot;) then
table.insert(result, team)
end
end
return result
end
local supportFriends = false
local currentBoardType = &quot;PlayerList&quot;
local currentStatCount = 0
local createBoardsFunction = nil
local playerTable = {}
local teamTable = {}
local teamColorTable = {}
local removePlayerFunction = nil
local recreatePlayerFunction = nil
local addPlayerFunction = function(player)
if recreatePlayerFunction then
recreatePlayerFunction(player)
end
end
local sortPlayerListsFunction = nil
local minimizedState = nil
local bigWindowImposter = nil
local smallWindowPosition = UDim2.new(0, -20, 0,5)--UDim2.new(0, 0, 0,0)
local smallWindowSize = UDim2.new(1,0,1,0)--UDim2.new(1,5,1,0)
local bigWindowSize = UDim2.new(0.6,0,0.6,0)
local bigWindowPosition = UDim2.new(.2, 0, .2,0)
local debounceTeamsChanged = false
local currentWindowState = &quot;Small&quot;
local previousWindowState = nil
local transitionWindowsFunction = nil
local container = nil
local topRightTrayContainer = nil
local playerContextMenu = nil
local contextMenuElements = {}
local function addContextMenuLabel(getText1, getText2, isVisible)
local t = {}
t.Type = &quot;Label&quot;
t.GetText1 = getText1
t.GetText2 = getText2
t.IsVisible = isVisible
table.insert(contextMenuElements, t)
end
local function addContextMenuButton(text, isVisible, isActive, doIt)
local t = {}
t.Text = text
t.Type = &quot;Button&quot;
t.IsVisible = isVisible
t.IsActive = isActive
t.DoIt = doIt
table.insert(contextMenuElements, t)
end
local function getFriendStatus(player)
if player == game.Players.LocalPlayer then
return Enum.FriendStatus.NotFriend
else
return game.Players.LocalPlayer:GetFriendStatus(player)
end
end
--Populate the ContextMenus
addContextMenuLabel(
--GetText1
function(player)
return &quot;Loading...&quot;
end,
--GetText2
nil,
--IsVisible
function(player)
return getFriendStatus(player) == Enum.FriendStatus.Unknown
end)
--[[
addContextMenuLabel(
--GetText1
function(player)
return player.Name
end,
--GetText2
nil,
--IsVisible
function(player)
return true
end)]]--
addContextMenuButton(&quot;Send &quot; .. friendWord .. &quot; Request&quot;,
--IsVisible
function(player)
return getFriendStatus(player) == Enum.FriendStatus.NotFriend
end,
--IsActive
function(player)
return true
end,
--DoIt
function(player)
return game.Players.LocalPlayer:RequestFriendship(player)
end
)
addContextMenuButton(&quot;Un&quot; .. friendWordLowercase,
--IsVisible
function(player)
return getFriendStatus(player) == Enum.FriendStatus.Friend
end,
--IsActive
function(player)
return true
end,
--DoIt
function(player)
return game.Players.LocalPlayer:RevokeFriendship(player)
end
)
addContextMenuButton(&quot;Accept &quot; .. friendWord .. &quot; Request&quot;,
--IsVisible
function(player)
return getFriendStatus(player) == Enum.FriendStatus.FriendRequestReceived
end,
--IsActive
function(player)
return true
end,
--DoIt
function(player)
return game.Players.LocalPlayer:RequestFriendship(player)
end
)
addContextMenuButton(&quot;Deny &quot; .. friendWord .. &quot; Request&quot;,
--IsVisible
function(player)
return getFriendStatus(player) == Enum.FriendStatus.FriendRequestReceived
end,
--IsActive
function(player)
return true
end,
--DoIt
function(player)
return game.Players.LocalPlayer:RevokeFriendship(player)
end
)
addContextMenuButton(&quot;Cancel &quot; .. friendWord .. &quot; Request&quot;,
--IsVisible
function(player)
return getFriendStatus(player) == Enum.FriendStatus.FriendRequestSent
end,
--IsActive
function(player)
return true
end,
--DoIt
function(player)
return game.Players.LocalPlayer:RevokeFriendship(player)
end
)
local function getStatColumns(players)
for i, player in ipairs(players) do
local leaderstats = player:FindFirstChild(&quot;leaderstats&quot;)
if leaderstats then
--print(player, &quot; is King of the List&quot;)
local stats = {}
local children = leaderstats:GetChildren()
if children then
for i, stat in ipairs(children) do
if stat:IsA(&quot;IntValue&quot;) then
table.insert(stats, stat.Name)
else
--TODO: This should check for IntValue only but current ScoreHud does not
table.insert(stats, stat.Name)
end
end
end
return stats
end
end
return nil
end
local function determineBoardType()
local players = getPlayers()
local foundLeaderstats = false
local numStats = 0
local foundTeam = false
local stats = getStatColumns(players)
if stats then
foundLeaderstats = true
numStats = #stats
end
for i, player in ipairs(players) do
if not foundTeam then
if not player.Neutral then
foundTeam = true
break
end
end
end
if foundLeaderstats and foundTeam then
return &quot;TeamScore&quot;, numStats
elseif foundLeaderstats then
return &quot;PlayerScore&quot;, numStats
elseif foundTeam then
return &quot;TeamList&quot;, numStats
else
return &quot;PlayerList&quot;, numStats
end
end
local function toggleBigWindow()
if container == nil then
return
end
if currentWindowState == &quot;Big&quot; then
--Hide it
if previousWindowState == nil or previousWindowState == &quot;Big&quot; or previousWindowState == &quot;None&quot; then
transitionWindowsFunction(&quot;None&quot;)
else
transitionWindowsFunction(&quot;Small&quot;)
end
else
previousWindowState = currentWindowState
transitionWindowsFunction(&quot;Big&quot;)
end
end
local previousBigPlayerList = nil
local function rebuildBoard(owner, boardType, numStats)
print(&quot;RebuildBoard&quot;)
if topRightTrayContainer == nil then
topRightTrayContainer = owner:FindFirstChild(&quot;PlayerListTopRightFrame&quot;)
if topRightTrayContainer == nil then
topRightTrayContainer = Instance.new(&quot;Frame&quot;)
topRightTrayContainer.Name = &quot;PlayerListTopRightFrame&quot;
topRightTrayContainer.BackgroundTransparency = 1
topRightTrayContainer.Size = UDim2.new(0.2, 16, 0.42, 16)--UDim2.new(0.2, 0, 0.42, 0)
topRightTrayContainer.Position = UDim2.new(0.8, 0, 0, 0)--UDim2.new(0.8, 0, 0, 0)
topRightTrayContainer.Parent = container
end
end
if minimizedState == nil then
minimizedState = Instance.new(&quot;Frame&quot;)
minimizedState.Name = &quot;MinimizedPlayerlist&quot;
minimizedState.BackgroundTransparency = 1
minimizedState.Position = UDim2.new(1, -166, 0,0) --UDim2.new(1, -153, 0,0)
minimizedState.Size = UDim2.new(0, 151, 0, 30)
--[[local playerListButton = Instance.new(&quot;ImageButton&quot;)
playerListButton.Name = &quot;GoBigButton&quot;
playerListButton.Image = &quot;rbxasset://textures/ui/playerlist_hidden_maximize.png&quot;
playerListButton.BackgroundTransparency = 1
playerListButton.Size = UDim2.new(0.0, 116, 0, 30)
playerListButton.Position = UDim2.new(0, 35, 0, 0)
playerListButton.MouseButton1Click:connect(
function()
toggleBigWindow()
end)
playerListButton.Parent = minimizedState]]
playerListButton = Instance.new(&quot;ImageButton&quot;)
playerListButton.Name = &quot;GoSmallButton&quot;
playerListButton.Image = &quot;rbxasset://textures/ui/playerlist_hidden_small.png&quot;
playerListButton.BackgroundTransparency = 1
playerListButton.Size = UDim2.new(0.0, 35, 0, 30)
playerListButton.Position = UDim2.new(1, -35, 0, 0)
playerListButton.MouseButton1Click:connect(
function()
transitionWindowsFunction(&quot;Small&quot;)
end)
playerListButton.Parent = minimizedState
minimizedState.Visible = false
robloxLock(minimizedState)
minimizedState.Parent = topRightTrayContainer
end
if bigWindowImposter == nil then
bigWindowImposter = owner:FindFirstChild(&quot;BigPlayerListWindowImposter&quot;)
if bigWindowImposter == nil then
bigWindowImposter = Instance.new(&quot;Frame&quot;)
bigWindowImposter.Name = &quot;BigPlayerListWindowImposter&quot;
bigWindowImposter.Visible = false
--bigWindowImposter.Style = Enum.FrameStyle.RobloxRound
bigWindowImposter.BackgroundColor3 = Color3.new(0,0,0)
bigWindowImposter.BackgroundTransparency = 0.7
bigWindowImposter.BorderSizePixel = 0
--bigWindowImposter.Size = UDim2.new(0.4, 0, 0.4, 0)
bigWindowImposter.Size = UDim2.new(0.4, 7, 0.4, 7)
bigWindowImposter.Position = UDim2.new(0.3, 0, 0.3, 0)
robloxLock(bigWindowImposter)
bigWindowImposter.Parent = container
end
end
if container == nil or container ~= owner then
container = owner
topRightTrayContainer.Parent = container
bigWindowImposter.Parent = container
end
local smallVisible = true
local bigVisible = false
if container then
if topRightTrayContainer then
--Delete the old boards
if topRightTrayContainer:FindFirstChild(&quot;SmallPlayerlist&quot;) then
smallVisible = topRightTrayContainer.SmallPlayerlist.Visible
topRightTrayContainer.SmallPlayerlist.Parent = nil
print(&quot;Removed small playerlist&quot;)
else
print(&quot;Did not remove small playerlist&quot;)
end
end
if container:FindFirstChild(&quot;BigPlayerlist&quot;) then
bigVisible = container.BigPlayerlist.Visible or (previousBigPlayerList ~= nil)
container.BigPlayerlist.Parent = nil
if previousBigPlayerList ~= nil then
pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end)
previousBigPlayerList = nil
end
end
end
local smallBoard, bigBoard = createBoardsFunction(boardType, numStats)
if smallBoard then
smallBoard.Visible = smallVisible
smallBoard.Parent = topRightTrayContainer
end
if bigBoard then
if bigVisible then
previousBigPlayerList = bigBoard
local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(previousBigPlayerList, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
previousBigPlayerList.Visible = true
end)
end)
bigBoard.Visible = bigVisible
else
bigBoard.Visible = false
end
bigBoard.Parent = container
end
return container
end
local function showBigPlayerWindow()
if container:FindFirstChild(&quot;BigPlayerlist&quot;) then
if container.BigPlayerlist.Visible then
return
end
end
bigWindowImposter.Visible = true
bigWindowImposter:TweenSizeAndPosition(bigWindowSize, bigWindowPosition, Enum.EasingDirection.Out, bigEasingStyle, 0.3, true,
function(state)
if state == Enum.TweenStatus.Completed then
bigWindowImposter.Visible = false
if container:FindFirstChild(&quot;BigPlayerlist&quot;) then
container.BigPlayerlist.Visible = true
end
end
end)
end
local function hideBigPlayerWindow(completed)
if playerContextMenu then
playerContextMenu.Visible = false
end
if container:FindFirstChild(&quot;BigPlayerlist&quot;) then
if container.BigPlayerlist.Visible == false and bigWindowImposter.Visible == false then
if completed then
completed()
end
--Already completely hidden
return
end
container.BigPlayerlist.Visible = false
end
local completedFunction = completed
bigWindowImposter.Visible = true
bigWindowImposter:TweenSizeAndPosition(UDim2.new(0.4, 0, 0.4, 0), UDim2.new(0.3, 0, 0.3, 0), Enum.EasingDirection.In, Enum.EasingStyle.Quart, 0.15, true,
function(state)
if state == Enum.TweenStatus.Completed then
bigWindowImposter.Visible = false
if completedFunction then
completedFunction()
end
end
end)
end
local function hideSmallPlayerWindow(completed)
if playerContextMenu then
playerContextMenu.Visible = false
end
if topRightTrayContainer:FindFirstChild(&quot;SmallPlayerlist&quot;) then
local completedFunction = completed
if topRightTrayContainer.SmallPlayerlist.Visible then
topRightTrayContainer.SmallPlayerlist:TweenPosition(UDim2.new(1,0,smallWindowPosition.Y.Scale, smallWindowPosition.Y.Offset), Enum.EasingDirection.Out, smallEasingStyle, 0.3, true,
function(state)
--print(state)
if state == Enum.TweenStatus.Completed then
if topRightTrayContainer:FindFirstChild(&quot;SmallPlayerlist&quot;) then
topRightTrayContainer.SmallPlayerlist.Visible = false
end
if completedFunction then
completedFunction()
end
end
end)
return
end
end
if completed then
completed()
end
end
transitionWindowsFunction = function(desiredState)
if desiredState == &quot;Big&quot; then
minimizedState.Visible = false
hideSmallPlayerWindow()
if previousBigPlayerList ~= nil then
if previousBigPlayerList ~= container:FindFirstChild(&quot;BigPlayerlist&quot;) then
pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end)
previousBigPlayerList = nil
previousBigPlayerList = container:FindFirstChild(&quot;BigPlayerlist&quot;)
end
else
previousBigPlayerList = container:FindFirstChild(&quot;BigPlayerlist&quot;)
end
if previousBigPlayerList then
local firstShow = false
local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(previousBigPlayerList, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
if not firstShow then
showBigPlayerWindow()
firstShow = true
else
previousBigPlayerList.Visible = true
end
end)
end)
if centerDialogSupported == false then
print(&quot;Exception&quot;, msg)
showBigPlayerWindow()
end
else
showBigPlayerWindow()
end
currentWindowState = &quot;Big&quot;
elseif desiredState == &quot;Small&quot; then
minimizedState.Visible = false
if previousBigPlayerList ~= nil then
pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end)
previousBigPlayerList = nil
end
hideBigPlayerWindow()
if topRightTrayContainer:FindFirstChild(&quot;SmallPlayerlist&quot;) then
if not topRightTrayContainer.SmallPlayerlist.Visible or topRightTrayContainer.SmallPlayerlist.Position ~= smallWindowPosition then
topRightTrayContainer.SmallPlayerlist.Visible = true
topRightTrayContainer.SmallPlayerlist:TweenPosition(smallWindowPosition, Enum.EasingDirection.Out, smallEasingStyle, 0.3, true)
end
end
currentWindowState = &quot;Small&quot;
elseif desiredState == &quot;None&quot; then
if previousBigPlayerList ~= nil then
pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end)
previousBigPlayerList = nil
end
local smallDone = false
local bigDone = false
hideSmallPlayerWindow(
function()
smallDone = true
if bigDone and smallDone then
minimizedState.Visible = true
end
end)
hideBigPlayerWindow(
function()
bigDone = true
if bigDone and smallDone then
minimizedState.Visible = true
end
end)
currentWindowState = &quot;None&quot;
end
end
local function getStatValuesForPlayer(player)
local leaderstats = player:FindFirstChild(&quot;leaderstats&quot;)
if leaderstats then
local children = leaderstats:GetChildren()
if children then
local result = {}
--Just go based on position
for i, stat in ipairs(children) do
if stat:IsA(&quot;IntValue&quot;) then
table.insert(result, stat)
else
table.insert(result, 0)
end
end
return result, leaderstats
end
end
return nil
end
--ChildAdded on Player (if it&apos;s name is &quot;leaderstats&quot;)
if UserSettings and LoadLibrary then
RbxGui,msg = t
print(&quot;Libraries loaded&quot;)
local function createTeamName(name, color)
local fontHeight = 20 --RbxGui.GetFontHeight(Enum.Font.ArialBold, Enum.FontSize.Size18)
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = &quot;Team-&quot; .. name
frame.BorderSizePixel = 0
frame.BackgroundTransparency = 0.5
frame.BackgroundColor3 = Color3.new(1,1,1)
frame.Size = UDim2.new(1, 0, 0, fontHeight)
frame.Position = UDim2.new(0,0,0,0)
local label = Instance.new(&quot;TextLabel&quot;)
label.Name = &quot;NameLabel&quot;
label.Text = &quot; &quot; .. name
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size18
label.Position = UDim2.new(0,0,0,0)
label.Size = UDim2.new(1,0,1,0)
label.TextColor3 = Color3.new(1,1,1)
label.BackgroundTransparency = 0.5
label.BackgroundColor3 = getColor(color)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label = RbxGui.AutoTruncateTextObject(label)
label.Parent = frame
return frame
end
local function getFriendStatusIcon(friendStatus)
if friendStatus == Enum.FriendStatus.Unknown or friendStatus == Enum.FriendStatus.NotFriend then
return nil
elseif friendStatus == Enum.FriendStatus.Friend then
return &quot;rbxasset://textures/ui/PlayerlistFriendIcon.png&quot;
elseif friendStatus == Enum.FriendStatus.FriendRequestSent then
return &quot;rbxasset://textures/ui/PlayerlistFriendRequestSentIcon.png&quot;
elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then
return &quot;rbxasset://textures/ui/PlayerlistFriendRequestReceivedIcon.png&quot;
else
error(&quot;Unknown FriendStatus: &quot; .. friendStatus)
end
end
local function getMembershipTypeIcon(membershipType)
--TODO: replace with proper icons
if membershipType == Enum.MembershipType.None then
return &quot;&quot;
elseif membershipType == Enum.MembershipType.BuildersClub then
return &quot;rbxasset://textures/ui/TinyBcIcon.png&quot;
elseif membershipType == Enum.MembershipType.TurboBuildersClub then
return &quot;rbxasset://textures/ui/TinyTbcIcon.png&quot;
elseif membershipType == Enum.MembershipType.OutrageousBuildersClub then
return &quot;rbxasset://textures/ui/TinyObcIcon.png&quot;
else
error(&quot;Uknown membershipType&quot; .. membershipType)
end
end
local function updatePlayerFriendStatus(nameObject, friendStatus)
local fontHeight = 20 --RbxGui.GetFontHeight(Enum.Font.ArialBold, Enum.FontSize.Size14)
local friendIconImage = getFriendStatusIcon(friendStatus)
nameObject.MembershipTypeLabel.FriendStatusLabel.Visible = (friendIconImage ~= nil)
if friendIconImage ~= nil then
--Show friend icon
nameObject.MembershipTypeLabel.FriendStatusLabel.Image = friendIconImage
nameObject.NameLabel.Position =UDim2.new(0,2*fontHeight,0,1)
nameObject.NameLabel.Size = UDim2.new(1,-2*fontHeight,1,-2)
else
--Hide the friend icon
nameObject.NameLabel.Position = UDim2.new(0,fontHeight+1,0,1)
nameObject.NameLabel.Size = UDim2.new(1,-(fontHeight+1),1,-2)
end
end
local function updatePlayerName(nameObject, membershipStatus, teamColor)
local fontHeight = 20 --RbxGui.GetFontHeight(Enum.Font.ArialBold, Enum.FontSize.Size14)
nameObject.Size = UDim2.new(1,0,0,fontHeight)
nameObject.MembershipTypeLabel.Image = getMembershipTypeIcon(membershipStatus)
end
local function updatePlayerNameColor(player, teamColor)
local function updatePlayerNameColorHelper(nameObject)
if teamColor ~= nil then
nameObject.NameLabel.TextColor3 = getColor(teamColor)
nameObject.NameLabel.FullNameLabel.TextColor3 = getColor(teamColor)
else
nameObject.NameLabel.TextColor3 = Color3.new(1,1,1)
nameObject.NameLabel.FullNameLabel.TextColor3 = Color3.new(1,1,1)
end
end
updatePlayerNameColorHelper(playerTable[player].NameObjectSmall)
updatePlayerNameColorHelper(playerTable[player].NameObjectBig)
end
local function createPlayerName(name, membershipStatus, teamColor, friendStatus)
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = &quot;Player_&quot; .. name
if lightBackground then
frame.BackgroundColor3 = Color3.new(1,1,1)
else
frame.BackgroundColor3 = Color3.new(1,1,1)
end
frame.BackgroundTransparency = 0.5
frame.BorderSizePixel = 0
local membershipStatusLabel = Instance.new(&quot;ImageLabel&quot;)
membershipStatusLabel.Name = &quot;MembershipTypeLabel&quot;
membershipStatusLabel.BackgroundTransparency = 1
membershipStatusLabel.Size = UDim2.new(1,0,1,0)
membershipStatusLabel.Position = UDim2.new(0,0,0,0)
membershipStatusLabel.SizeConstraint = Enum.SizeConstraint.RelativeYY
membershipStatusLabel.Parent = frame
local friendStatusLabel = Instance.new(&quot;ImageLabel&quot;)
friendStatusLabel.Name = &quot;FriendStatusLabel&quot;
friendStatusLabel.Visible = false
friendStatusLabel.BackgroundTransparency = 1
friendStatusLabel.Size = UDim2.new(1,0,1,0)
friendStatusLabel.Position = UDim2.new(1,0,0,0)
friendStatusLabel.Parent = membershipStatusLabel
local changeNameFunction
local nameLabel = Instance.new(&quot;TextLabel&quot;)
nameLabel.Name = &quot;NameLabel&quot;
nameLabel.Text = name
nameLabel.Font = Enum.Font.ArialBold
nameLabel.FontSize = Enum.FontSize.Size14
nameLabel.TextColor3 = Color3.new(1,1,1)
nameLabel.BackgroundTransparency = 1
nameLabel.BackgroundColor3 = Color3.new(0,0,0)
nameLabel.TextXAlignment = Enum.TextXAlignment.Left
nameLabel, changeNameFunction = RbxGui.AutoTruncateTextObject(nameLabel)
nameLabel.Parent = frame
updatePlayerName(frame, membershipStatus, teamColor)
if supportFriends then
updatePlayerFriendStatus(frame, friendStatus)
else
updatePlayerFriendStatus(frame, Enum.FriendStatus.NotFriend)
end
return frame, changeNameFunction
end
local function createStatColumn(i, numColumns, isTeam, color3, isHeader)
local textLabel = Instance.new(&quot;TextLabel&quot;)
textLabel.Name = &quot;Stat&quot; .. i
textLabel.TextColor3 = Color3.new(1,1,1)
textLabel.TextXAlignment = Enum.TextXAlignment.Right
textLabel.TextYAlignment = Enum.TextYAlignment.Center
textLabel.FontSize = Enum.FontSize.Size14
if isHeader then
textLabel.FontSize = Enum.FontSize.Size18
else
textLabel.FontSize = Enum.FontSize.Size14
end
if isHeader or isTeam then
textLabel.Font = Enum.Font.ArialBold
else
textLabel.Font = Enum.Font.Arial
end
if isTeam then
textLabel.BackgroundColor3 = color3
textLabel.Text = 0
else
textLabel.BackgroundColor3 = Color3.new(0,0,0)
textLabel.Text = &quot;&quot;
end
textLabel.BackgroundTransparency = 1
if i == numColumns then
textLabel.Size = UDim2.new(1/numColumns, -6, 1, 0)
else
textLabel.Size = UDim2.new(1/numColumns, -4, 1, 0)
end
textLabel.Position = UDim2.new((i-1) * (1/numColumns), 0, 0, 0)
return RbxGui.AutoTruncateTextObject(textLabel)
end
local function createStatHeaders(stats, numColumns, isBig)
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = &quot;Headers&quot;
frame.BorderSizePixel = 0
frame.BackgroundColor3 = Color3.new(0,0,0)
frame.BackgroundTransparency = 1
local nameSize
if isBig then
nameSize = 0.5
elseif numColumns == 1 then
nameSize = 0.7
elseif numColumns == 2 then
nameSize = 0.6
else
nameSize = 0.45
end
frame.Size = UDim2.new(1-nameSize, 0, 1,0)
if isBig then
frame.Position = UDim2.new(nameSize,-25, 0,0)
else
frame.Position = UDim2.new(nameSize,0, 0,0)
end
local i = 1
while i &lt;= numColumns do
local headerColumn, changeText = createStatColumn(i, numColumns, false, nil, true)
changeText(stats[i])
headerColumn.Parent = frame
i = i + 1
end
return frame, textChangers
end
local function createStatColumns(nameObject, numColumns, isTeam, isBig)
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = nameObject.Name .. &quot;_WithStats&quot;
frame.BorderSizePixel = 0
frame.BackgroundColor3 = nameObject.BackgroundColor3
frame.BackgroundTransparency = nameObject.BackgroundTransparency
frame.Size = nameObject.Size
frame.Position = nameObject.Position
nameObject.BackgroundTransparency = 1
if numColumns == 0 then
nameObject.Size = UDim2.new(1,0,1,0)
nameObject.Position = UDim2.new(0,0,0,0)
nameObject.Parent = frame
return frame
end
local statFrame = Instance.new(&quot;Frame&quot;)
statFrame.Name = &quot;Stats&quot;
if isTeam then
statFrame.BorderSizePixel = 0
statFrame.BackgroundColor3 = nameObject.NameLabel.BackgroundColor3
statFrame.BackgroundTransparency = nameObject.NameLabel.BackgroundTransparency
else
statFrame.BackgroundTransparency = 1
end
local nameSize
if isBig then
nameSize = 0.5
elseif numColumns == 1 then
nameSize = 0.7
elseif numColumns == 2 then
nameSize = 0.6
else
nameSize = 0.45
end
nameObject.Size = UDim2.new(nameSize, 0, 1, 0)
nameObject.Position = UDim2.new(0, 0, 0, 0)
statFrame.Size = UDim2.new(1-nameSize,0, 1,0)
statFrame.Position = UDim2.new(nameSize,0, 0,0)
nameObject.Parent = frame
statFrame.Parent = frame
local textChangers = {}
local i = 1
while i &lt;= numColumns do
local statColumn, changeText = createStatColumn(i, numColumns, isTeam, statFrame.BackgroundColor3)
statColumn.Parent = statFrame
table.insert(textChangers, changeText)
i = i + 1
end
return frame, statFrame, textChangers
end
local function createAlternatingRows(objects)
for i, line in ipairs(objects) do
if i % 2 == 0 then
line.BackgroundTransparency = 1
else
line.BackgroundTransparency = 0.95
end
end
end
local removeFromTeam = nil
local function clearTableEntry(obj, tableInfo)
if tableInfo.MainObjectSmall then
tableInfo.MainObjectSmall.Parent = nil
tableInfo.MainObjectSmall = nil
end
if tableInfo.MainObjectBig then
tableInfo.MainObjectBig.Parent = nil
tableInfo.MainObjectBig = nil
end
if tableInfo.Connections then
for i, connection in ipairs(tableInfo.Connections) do
connection:disconnect()
end
tableInfo.Connections = nil
end
if tableInfo.LeaderStatConnections then
for i, connection in ipairs(tableInfo.LeaderStatConnections) do
connection:disconnect()
end
tableInfo.LeaderStatConnections = nil
end
if tableInfo.CurrentTeam then
removeFromTeam(obj)
tableInfo.CurrentTeam = nil
end
if tableInfo.Players then
for i, player in ipairs(tableInfo.Players) do
playerTable[player].CurrentTeam = nil
end
tableInfo.Players = {}
end
if tableInfo.StatValues then
tableInfo.StatValues = nil
end
end
local function resetPlayerTable()
for player, info in pairs(playerTable) do
clearTableEntry(player, info)
playerTable[player] = nil
end
playerTable = {}
end
local function resetTeamTable()
for team, info in pairs(teamTable) do
clearTableEntry(team, info)
teamTable[team] = nil
end
teamTable = {}
teamColorTable = {}
end
local function getBoardTypeInfo()
local isTeam = (currentBoardType == &quot;TeamScore&quot; or currentBoardType == &quot;TeamList&quot;)
local isScore = (currentBoardType == &quot;TeamScore&quot; or currentBoardType == &quot;PlayerScore&quot;)
return isTeam, isScore
end
local function recomputeTeamScore(team, column)
if not team or team == &quot;Neutral&quot; then
return
end
local function recomputeScoreHelper(statChangers)
if statChangers and column &lt;= #statChangers then
local sum = 0
for i, p in ipairs(teamTable[team].Players) do
if playerTable[p].StatValues and column &lt;= #playerTable[p].StatValues then
sum = sum + playerTable[p].StatValues[column].Value
end
end
statChangers[column](sum)
end
end
recomputeScoreHelper(teamTable[team].StatChangersSmall)
recomputeScoreHelper(teamTable[team].StatChangersBig)
end
local function recomputeCompleteTeamScore(team)
local col = 1
while col &lt;= currentStatCount do
recomputeTeamScore(team, col)
col = col + 1
end
end
removeFromTeam = function(player)
if playerTable[player].CurrentTeam ~= nil then
ArrayRemove(teamTable[playerTable[player].CurrentTeam].Players, player)
recomputeCompleteTeamScore(playerTable[player].CurrentTeam)
playerTable[player].CurrentTeam = nil
end
end
local function assignToTeam(player)
local isTeam, isScore = getBoardTypeInfo()
if isTeam then
local newTeam = nil
if player.Neutral or teamColorTable[player.TeamColor.Name] == nil then
newTeam = &quot;Neutral&quot;
else
newTeam = teamColorTable[player.TeamColor.Name]
end
if playerTable[player].CurrentTeam == newTeam then
return
end
removeFromTeam(player)
playerTable[player].CurrentTeam = newTeam
table.insert(teamTable[newTeam].Players, player)
if newTeam == &quot;Neutral&quot; then
updatePlayerNameColor(player, nil)
else
updatePlayerNameColor(player, player.TeamColor)
end
recomputeCompleteTeamScore(newTeam)
--Relayout
if sortPlayerListsFunction then
sortPlayerListsFunction()
end
end
end
local function buildTeamObject(team, numStatColumns, suffix)
local isTeam, isScore = getBoardTypeInfo()
local teamObject = createTeamName(team.Name, team.TeamColor)
if not teamTable[team] then
teamTable[team] = {}
end
teamTable[team][&quot;NameObject&quot; .. suffix] = teamObject
if isScore then
local statObject
local textChangers
teamObject, statObject, textChangers = createStatColumns(teamObject, numStatColumns, true, suffix == &quot;Big&quot;)
teamTable[team][&quot;StatObject&quot; .. suffix] = statObject
teamTable[team][&quot;StatChangers&quot; .. suffix] = textChangers
end
teamTable[team][&quot;MainObject&quot; .. suffix] = teamObject
if not teamTable[team].Players then
teamTable[team].Players = {}
end
return teamObject
end
local currentContextMenuPlayer = nil
local function updatePlayerContextMenu(player)
currentContextMenuPlayer = player
local elementHeight = 20
local function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
local function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
if playerContextMenu == nil then
playerContextMenu = Instance.new(&quot;Frame&quot;)
playerContextMenu.Name = &quot;PlayerListContextMenu&quot;
playerContextMenu.BackgroundTransparency = 1
playerContextMenu.Visible = false
local playerContextMenuButton = Instance.new(&quot;TextButton&quot;)
playerContextMenuButton.Name = &quot;PlayerListContextMenuButton&quot;
playerContextMenuButton.Text = &quot;&quot;
playerContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
playerContextMenuButton.ZIndex = 4
playerContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
playerContextMenuButton.Visible = true
playerContextMenuButton.Parent = playerContextMenu
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == &quot;Button&quot; then
local button = Instance.new(&quot;TextButton&quot;)
button.Name = &quot;ContextButton&quot; .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = &quot; &quot; .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 4
button.Parent = playerContextMenuButton
button.MouseButton1Click:connect(function()
if button.Active then
local success, result = pcall(function() element.DoIt(currentContextMenuPlayer) end)
playerContextMenu.Visible = false
end
end)
button.MouseEnter:connect(function()
if button.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active then
clearHighlight(button)
end
end)
contextElement.Button = button
contextElement.Element = button
elseif element.Type == &quot;Label&quot; then
local frame = Instance.new(&quot;Frame&quot;)
frame.Name = &quot;ContextLabel&quot; .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new(&quot;TextLabel&quot;)
label.Name = &quot;Text1&quot;
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(&quot;TextLabel&quot;)
label.Name = &quot;Text2&quot;
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 = playerContextMenuButton
element.Label = frame
element.Element = frame
end
end
playerContextMenu.ZIndex = 4
playerContextMenu.MouseLeave:connect(function() playerContextMenu.Visible = false end)
robloxLock(playerContextMenu)
playerContextMenu.Parent = NewPlayerListGui
end
local elementPos = 0
for i, contextElement in ipairs(contextMenuElements) do
local isVisible = false
if contextElement.IsVisible then
local success, visible = pcall(function() return contextElement.IsVisible(currentContextMenuPlayer) end)
if success then
isVisible = visible
else
print(&quot;Error in IsVisible call: &quot; .. visible)
end
end
if contextElement.Type == &quot;Button&quot; then
contextElement.Button.Visible = isVisible
if contextElement.Button.Visible then
isVisible = true
clearHighlight(contextElement.Button)
if contextElement.IsActive then
local success, active = pcall(function() return contextElement.IsActive(currentContextMenuPlayer) end)
if success then
contextElement.Button.Active = active
else
print(&quot;Error in IsActive call: &quot; .. active)
end
end
if contextElement.Button.Active then
contextElement.Button.TextColor3 = Color3.new(1,1,1)
else
contextElement.Button.TextColor3 = Color3.new(0.7,0.7,0.7)
end
end
elseif contextElement.Type == &quot;Label&quot; then
contextElement.Label.Visible = isVisible
if contextElement.Label.Visible then
local success, text = pcall(function() return contextElement.GetText1(currentContextMenuPlayer) end)
if success then
contextElement.Label1.Text = &quot; &quot; .. text
else
print(&quot;Error in GetText1 call: &quot; .. text)
end
if contextElement.GetText2 then
local success, text = pcall(function() return contextElement.GetText2(currentContextMenuPlayer) end)
if success then
contextElement.Label2.Text = &quot; &quot; .. text
else
print(&quot;Error in GetText2 call: &quot; .. text)
end
end
end
end
if isVisible then
contextElement.Element.Position = UDim2.new(0,-4, 0, elementPos * elementHeight - 4)
elementPos = elementPos + 1
end
end
playerContextMenu.Size = UDim2.new(0, 150, 0, elementPos*elementHeight + 13 + 20)
end
local function showPlayerMenu(player, x, y)
updatePlayerContextMenu(player)
x = x - (playerContextMenu.AbsoluteSize.X/2)
if x + playerContextMenu.AbsoluteSize.X &gt;= NewPlayerListGui.AbsoluteSize.X then
x = NewPlayerListGui.AbsoluteSize.X - playerContextMenu.AbsoluteSize.X
end
playerContextMenu.Visible = true
playerContextMenu.Position = UDim2.new(0, x, 0, y-playerContextMenu.AbsoluteSize.Y)
end
local function buildPlayerObject(player, numStatColumns, suffix)
local isTeam, isScore = getBoardTypeInfo()
local playerObject = nil
local changePlayerNameFunction = nil
local currentColor = nil
if isTeam and not player.Neutral then
currentColor = player.TeamColor.Color
else
currentColor = Color3.new(1,1,1)
end
playerObject, changePlayerNameFunction = createPlayerName(player.Name, player.MembershipType, currentColor, getFriendStatus(player))
if not playerTable[player] then
playerTable[player] = {}
end
if not playerTable[player].Connections then
playerTable[player].Connections = {}
end
if not playerTable[player].CurrentTeam then
playerTable[player].CurrentTeam = nil
end
playerTable[player][&quot;NameObject&quot; .. suffix] = playerObject
playerTable[player][&quot;ChangeName&quot; .. suffix] = changePlayerNameFunction
if isScore then
local statObject = nil
local textChangers = nil
playerObject, statObject, textChangers = createStatColumns(playerObject, numStatColumns, false, suffix == &quot;Big&quot;)
playerTable[player][&quot;StatObject&quot; .. suffix]= statObject
playerTable[player][&quot;StatChangers&quot; .. suffix] = textChangers
local statValues, leaderstats = getStatValuesForPlayer(player)
if not statValues or #statValues &lt; numStatColumns then
if not playerTable[player].LeaderStatConnections then
playerTable[player].LeaderStatConnections = {}
end
--Setup a listener to see when this data gets filled in
if not leaderstats then
--print(&quot;No leaderstats for &quot;, player)
--We don&apos;t even have a leaderstats child, wait for one
table.insert(playerTable[player].LeaderStatConnections,
player.ChildAdded:connect(
function(child)
if child.Name == &quot;leaderstats&quot; then
--print(&quot;Got a leaderstats for &quot;, player)
--Connections will be torn down
recreatePlayerFunction(player)
else
--print(&quot;Unknown child, listening for connection&quot;)
table.insert(playerTable[player].LeaderStatConnections,
child.Changed:connect(
function(prop)
if prop == &quot;Name&quot; and child.Name == &quot;leaderstats&quot; then
--Connections will be torn down
recreatePlayerFunction(player)
end
end))
end
end))
else
--print(&quot;Need more children&quot;)
--We have a leaderstats, but not enough children, recreate if we get them
table.insert(playerTable[player].LeaderStatConnections,
leaderstats.ChildAdded:connect(
function(child)
--TODO only look for IntValue
recreatePlayerFunction(player)
end)
)
table.insert(playerTable[player].LeaderStatConnections,
leaderstats.AncestryChanged:connect(
function(child)
--We got deleted, try again
recreatePlayerFunction(player)
end)
)
end
end
if statValues then
if not playerTable[player].StatValues then
playerTable[player].StatValues = {}
end
local pos = 1
while pos &lt;= numStatColumns and pos &lt;= #statValues do
local currentColumn = pos
local statValue = statValues[pos]
local statChanger = textChangers[pos]
local updateStat = function(val)
statChanger(val)
recomputeTeamScore(playerTable[player].CurrentTeam, currentColumn)
end
if pos &gt; #playerTable[player].StatValues then
table.insert(playerTable[player].StatValues, statValue)
end
table.insert(playerTable[player].Connections,
statValue.Changed:connect(updateStat)
)
table.insert(playerTable[player].Connections,
statValue.AncestryChanged:connect(
function()
recreatePlayerFunction(player)
end)
)
updateStat(statValue.Value)
pos = pos + 1
end
end
end
if supportFriends and player ~= game.Players.LocalPlayer and player.userId &gt; 0 and game.Players.LocalPlayer.userId &gt; 0 then
local button = Instance.new(&quot;TextButton&quot;)
button.Name = playerObject.Name .. &quot;Button&quot;
button.Text = &quot;&quot;
button.Active = false
button.Size = playerObject.Size
button.Position = playerObject.Position
button.BackgroundColor3 = playerObject.BackgroundColor3
local secondButton = Instance.new(&quot;TextButton&quot;)
secondButton.Name = playerObject.Name .. &quot;RealButton&quot;
secondButton.Text = &quot;&quot;
secondButton.BackgroundTransparency = 1
secondButton.BackgroundColor3 = playerObject.BackgroundColor3
secondButton.Parent.BackgroundTransparency = 1
secondButton.Parent.Visible = true
secondButton.ZIndex = 2
secondButton.Size = UDim2.new(1,0,1,0)
local previousTransparency = nil
table.insert(playerTable[player].Connections,
secondButton.MouseEnter:connect(--button.MouseEnter:connect(
function()
if previousTransparency == nil then
previousTransparency = secondButton--[[button]].BackgroundTransparency
end
if lightBackground then
--button.BackgroundColor3 = Color3.new(0,0,0)
--button.BackgroundTransparency = 0
secondButton.Parent.BackgroundTransparency = 0
else
--button.BackgroundColor3 = Color3.new(1,1,1)
--secondButton.button.BackgroundTransparency = 1--0.80
secondButton.Parent.BackgroundTransparency = 1
end
end))
table.insert(playerTable[player].Connections,
secondButton.MouseLeave:connect(--button.MouseLeave:connect(
function()
if previousTransparency ~= nil then
if lightBackground then
--button.BackgroundColor3 = Color3.new(1,1,1)
--button.BackgroundTransparency = previousTransparency
else
--secondButtonbutton.BackgroundColor3 = Color3.new(1,1,1)
--nbutton.BackgroundTransparency = previousTransparency
end
previousTransparency = nil
end
secondButton.Parent.BackgroundTransparency = 1
end))
local mouseDownX, mouseDownY
table.insert(playerTable[player].Connections,
secondButton.MouseButton1Down:connect(function(x,y)
mouseDownX = x
mouseDownY = y
end))
table.insert(playerTable[player].Connections,
secondButton.MouseButton1Click:connect(function()
showPlayerMenu(player, mouseDownX, secondButton.AbsolutePosition.Y + secondButton.AbsoluteSize.Y )
end))
playerObject.BackgroundTransparency = 1
playerObject.Size = UDim2.new(1,0,1,0)
playerObject.Position = UDim2.new(0,0,0,0)
playerObject.Parent = button
playerTable[player][&quot;MainObject&quot; .. suffix] = button
playerObject = button
else
playerTable[player][&quot;MainObject&quot; .. suffix] = playerObject
if player == game.Players.LocalPlayer and supportFriends then
table.insert(playerTable[player].Connections,
player.FriendStatusChanged:connect(
function(otherPlayer, friendStatus)
if playerTable[otherPlayer] then
updatePlayerFriendStatus(playerTable[otherPlayer][&quot;NameObject&quot; .. suffix], friendStatus)
end
end)
)
end
end
table.insert(playerTable[player].Connections,
player.Changed:connect(
function(prop)
if prop == &quot;MembershipType&quot; then
updatePlayerName(playerTable[player][&quot;NameObject&quot; .. suffix], player.MembershipType, currentColor)
elseif prop == &quot;Name&quot; then
playerTable[player][&quot;ChangeName&quot; .. suffix](player.Name)
elseif prop == &quot;Neutral&quot; or prop == &quot;TeamColor&quot; then
assignToTeam(player)
end
end)
)
return playerObject
end
local function orderScrollList(scrollOrder, objectName, scrollFrame)
local pos = 0
local order = {}
local isTeam, isScore = getBoardTypeInfo()
for i, obj in ipairs(scrollOrder) do
order[obj] = 0
end
if isTeam then
local teams = getTeams()
for i, team in ipairs(teams) do
--print(team, objectName, teamTable[team][objectName])
order[teamTable[team][objectName]] = pos
pos = pos + 1
for i, player in ipairs(teamTable[team].Players) do
if playerTable[player] then
order[playerTable[player][objectName]] = pos
pos = pos + 1
end
end
end
if #teamTable[&quot;Neutral&quot;].Players &gt; 0 then
teamTable[&quot;Neutral&quot;][objectName].Parent = scrollFrame
order[teamTable[&quot;Neutral&quot;][objectName]] = pos
pos = pos + 1
for i, player in ipairs(teamTable[&quot;Neutral&quot;].Players) do
order[playerTable[player][objectName]] = pos
pos = pos + 1
end
else
teamTable[&quot;Neutral&quot;][objectName].Parent = nil
end
else
local players = getPlayers()
for i, player in ipairs(players) do
order[playerTable[player][objectName]] = pos
pos = pos + 1
end
end
table.sort(scrollOrder,
function(a,b)
return order[a] &lt; order[b]
end)
end
local function createPlayerListBasics(frame, isBig)
local headerFrame = Instance.new(&quot;Frame&quot;)
headerFrame.Name = &quot;Header&quot;
headerFrame.BackgroundTransparency = 1
headerFrame.Size = UDim2.new(1,-13,0,26)
headerFrame.Position = UDim2.new(0,0,0,0) --UDim2.new(0,-6,0,-6)
headerFrame.Parent = frame
local lowerPaneFrame = Instance.new(&quot;Frame&quot;)
lowerPaneFrame.Name = &quot;ScrollingArea&quot;
lowerPaneFrame.BackgroundTransparency = 1
lowerPaneFrame.Size = UDim2.new(1,-3,1,-26)
lowerPaneFrame.Position = UDim2.new(0,0,0,26)
lowerPaneFrame.Parent = frame
local scrollOrder = {}
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(scrollOrder)
local scrollBar = Instance.new(&quot;Frame&quot;)
scrollBar.Name = &quot;ScrollBar&quot;
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
if isBig then scrollBar.Size = UDim2.new(0, 17, 1, -61) end
scrollBar.Parent = lowerPaneFrame
scrollFrame.Parent = lowerPaneFrame
scrollUp.Parent = lowerPaneFrame
scrollDown.Parent = lowerPaneFrame
if isBig then
scrollFrame.Position = UDim2.new(0,0,0,0) --UDim2.new(0,-7,0,0)
scrollUp.Position = UDim2.new(1,-41,0,5) --UDim2.new(1,-19,0,0)
scrollDown.Position = UDim2.new(1,-41,1,-35) -- UDim2.new(1,-19,1,-15)
scrollBar.Position = UDim2.new(1, -41, 0, 24) -- UDim2.new(1, -19, 0, 19)
scrollFrame.Size = UDim2.new(1,-48,1,0)
headerFrame.Size = UDim2.new(1,-20,0,32)
else
scrollBar.Position = UDim2.new(1, -19, 0, 14) --UDim2.new(1, -17, 0, 19)
scrollFrame.Position = UDim2.new(0,1,0,0) -- UDim2.new(0,-5,0,0)
scrollUp.Position = UDim2.new(1,-19,0,-5) --UDim2.new(1,-17,0,0)
scrollDown.Position = UDim2.new(1,-19,1,-20) --UDim2.new(1,-17,1,-15)
lowerPaneFrame.Position = UDim2.new(0,0,0,30)
local toggleScrollBar = function(visible)
if visible then
scrollFrame.Size = UDim2.new(1,-16,1,0)
headerFrame.Size = UDim2.new(1,-16,0,32)
else
scrollFrame.Size = UDim2.new(1,0,1,0)--UDim2.new(1,5,1,0)
headerFrame.Size = UDim2.new(1,5,0,32)
end
scrollUp.Visible = visible
scrollDown.Visible = visible
scrollBar.Visible = visible
end
scrollUp.Changed:connect(function(prop)
if prop == &quot;Active&quot; then
toggleScrollBar(scrollUp.Active or scrollDown.Active)
end
end)
scrollDown.Changed:connect(function(prop)
if prop == &quot;Active&quot; then
toggleScrollBar(scrollUp.Active or scrollDown.Active)
end
end)
toggleScrollBar(scrollUp.Active or scrollDown.Active)
end
return headerFrame, scrollFrame, recalculateScroll, scrollOrder
end
createBoardsFunction = function (boardType, numStatColumns)
print(&quot;Create Boards&quot;)
local smallFrame = Instance.new(&quot;Frame&quot;)
smallFrame.Name = &quot;SmallPlayerlist&quot;
smallFrame.Position = smallWindowPosition
smallFrame.Active = false
smallFrame.Size = smallWindowSize
--smallFrame.Style = Enum.FrameStyle.RobloxRound
smallFrame.BackgroundColor3 = Color3.new(0,0,0)
smallFrame.BackgroundTransparency = 0.7
smallFrame.BorderSizePixel = 0
local bigFrame = Instance.new(&quot;Frame&quot;)
bigFrame.Name = &quot;BigPlayerlist&quot;
bigFrame.Size = bigWindowSize
bigFrame.Position = bigWindowPosition
--bigFrame.Style = Enum.FrameStyle.RobloxRound
bigFrame.BackgroundColor3 = Color3.new(0,0,0)
bigFrame.BackgroundTransparency = 0.7
bigFrame.BorderSizePixel = 0
bigFrame.Visible = false
local bigFrameWrapper = Instance.new(&quot;Frame&quot;)
bigFrameWrapper.Name = &quot;Expander&quot;
--bigFrameWrapper.Size = UDim2.new(1,5,1,0)
bigFrameWrapper.Size = UDim2.new(1,21,1,16)
bigFrameWrapper.Position = UDim2.new(0, 0, 0,0)
bigFrameWrapper.BackgroundTransparency = 1
bigFrameWrapper.Parent = bigFrame
local smallHeaderFrame, scrollFrameSmall, recalculateScrollSmall, scrollOrderSmall = createPlayerListBasics(smallFrame, false)
local bigHeaderFrame, scrollFrameBig, recalculateScrollBig, scrollOrderBig = createPlayerListBasics(bigFrameWrapper, true)
local playerListButton = Instance.new(&quot;ImageButton&quot;)
playerListButton.Name = &quot;GoBigButton&quot;
playerListButton.BackgroundTransparency = 1
playerListButton.Image = &quot;rbxasset://textures/ui/playerlist_small_maximize.png&quot;
playerListButton.Size = UDim2.new(0.0, 35, 0, 29)
playerListButton.Position = UDim2.new(0, 0, 0, 0)
playerListButton.MouseButton1Click:connect(
function()
toggleBigWindow()
end)
playerListButton.Parent = smallHeaderFrame
playerListButton = Instance.new(&quot;ImageButton&quot;)
playerListButton.Name = &quot;CloseButton&quot;
playerListButton.BackgroundTransparency = 1
playerListButton.Image = &quot;rbxasset://textures/ui/playerlist_small_hide.png&quot;
playerListButton.Size = UDim2.new(0.0, 38, 0, 29)
playerListButton.Position = UDim2.new(0, 35, 0, 0)
playerListButton.MouseButton1Click:connect(
function()
transitionWindowsFunction(&quot;None&quot;)
end)
playerListButton.Parent = smallHeaderFrame
playerListButton = Instance.new(&quot;ImageButton&quot;)
playerListButton.Name = &quot;CloseButton&quot;
playerListButton.Image = &quot;rbxasset://textures/ui/playerlist_big_hide.png&quot;
playerListButton.BackgroundTransparency = 1
playerListButton.Size = UDim2.new(0.0, 29, 0, 29)
playerListButton.Position = UDim2.new(1, -30, 0.5, -15)
playerListButton.MouseButton1Click:connect(
function()
toggleBigWindow()
end)
playerListButton.Parent = bigHeaderFrame
local placeName = Instance.new(&quot;TextLabel&quot;)
placeName.Name = &quot;PlaceName&quot;
placeName.Text = &quot; Player List&quot;
placeName.FontSize = Enum.FontSize.Size24
placeName.TextXAlignment = Enum.TextXAlignment.Left
placeName.Font = Enum.Font.ArialBold
placeName.BackgroundTransparency = 1
placeName.TextColor3 = Color3.new(1,1,1)
placeName.Size = UDim2.new(0.5, 0, 1, 0)
placeName.Position = UDim2.new(0, 0, 0.0, 0)
placeName = RbxGui.AutoTruncateTextObject(placeName)
placeName.Parent = bigHeaderFrame
currentBoardType = boardType
currentStatCount = numStatColumns
local isTeam, isScore = getBoardTypeInfo()
local players = getPlayers()
if isScore then
local statColumns = getStatColumns(players)
numStatColumns = #statColumns
if numStatColumns &gt; 3 then
numStatColumns = 3
end
createStatHeaders(statColumns, numStatColumns, false).Parent = smallHeaderFrame
createStatHeaders(statColumns, currentStatCount, true).Parent = bigHeaderFrame
end
--Clean up all old stuff
resetPlayerTable()
for i, player in ipairs(players) do
local playerObject = buildPlayerObject(player, numStatColumns, &quot;Small&quot;)
table.insert(scrollOrderSmall, playerObject)
playerObject.Parent = scrollFrameSmall
playerObject = buildPlayerObject(player, currentStatCount, &quot;Big&quot;)
table.insert(scrollOrderBig, playerObject)
playerObject.Parent = scrollFrameBig
end
--Clean up old stuff
resetTeamTable()
local teamStatObjects = {}
if isTeam then
local teams = getTeams()
local i = #teams
while i &gt;= 1 do
--We go backwards so the &quot;first&quot; team color gets the team
local team = teams[i]
teamColorTable[team.TeamColor.Name] = team
i = i - 1
end
--Adding/Removing a Team causes a full invalidation of the board
for i, team in ipairs(teams) do
local teamObject = buildTeamObject(team, numStatColumns, &quot;Small&quot;)
table.insert(scrollOrderSmall, teamObject)
teamObject.Parent = scrollFrameSmall
teamObject = buildTeamObject(team, currentStatCount, &quot;Big&quot;)
table.insert(scrollOrderBig, teamObject)
teamObject.Parent = scrollFrameBig
end
teamTable[&quot;Neutral&quot;] = {}
teamTable[&quot;Neutral&quot;].Players = {}
local neutralTeamObject = createTeamName(&quot;Neutral&quot;, BrickColor.palette(8))
teamTable[&quot;Neutral&quot;].NameObjectSmall = neutralTeamObject
teamTable[&quot;Neutral&quot;].StatObjectSmall = nil
teamTable[&quot;Neutral&quot;].MainObjectSmall = neutralTeamObject
table.insert(scrollOrderSmall, neutralTeamObject)
neutralTeamObject = createTeamName(&quot;Neutral&quot;, BrickColor.palette(8))
teamTable[&quot;Neutral&quot;].NameObjectBig = neutralTeamObject
teamTable[&quot;Neutral&quot;].StatObjectBig = nil
teamTable[&quot;Neutral&quot;].MainObjectBig = neutralTeamObject
table.insert(scrollOrderBig, neutralTeamObject)
local neutralPlayers = {}
for i, player in ipairs(players) do
assignToTeam(player)
end
end
removePlayerFunction = function(player)
if playerTable[player] then
ArrayRemove(scrollOrderSmall, playerTable[player].MainObjectSmall)
ArrayRemove(scrollOrderBig, playerTable[player].MainObjectBig)
clearTableEntry(player, playerTable[player])
playerTable[player] = nil
end
end
recreatePlayerFunction = function(player)
removePlayerFunction(player)
local playerObject = buildPlayerObject(player, numStatColumns, &quot;Small&quot;)
table.insert(scrollOrderSmall, playerObject)
robloxLock(playerObject)
playerObject.Parent = scrollFrameSmall
playerObject = buildPlayerObject(player, currentStatCount, &quot;Big&quot;)
table.insert(scrollOrderBig, playerObject)
robloxLock(playerObject)
playerObject.Parent = scrollFrameBig
local isTeam, isScore = getBoardTypeInfo()
if isTeam then
assignToTeam(player)
end
sortPlayerListsFunction()
end
sortPlayerListsFunction = function()
orderScrollList(scrollOrderSmall, &quot;MainObjectSmall&quot;, scrollFrameSmall)
recalculateScrollSmall()
createAlternatingRows(scrollOrderSmall)
orderScrollList(scrollOrderBig, &quot;MainObjectBig&quot;, scrollFrameBig)
recalculateScrollBig()
createAlternatingRows(scrollOrderBig)
end
sortPlayerListsFunction()
robloxLock(smallFrame)
robloxLock(bigFrame)
return smallFrame, bigFrame
end
--Teams changing invalidates the whole board
local function teamsChanged()
if debounceTeamsChanged then
return
end
debounceTeamsChanged = true
wait()
rebuildBoard(NewPlayerListGui, determineBoardType())
debounceTeamsChanged = false
end
local checkIfBoardChanged = function()
local newBoardType, numStats = determineBoardType()
if newBoardType ~= currentBoardType or numStats ~= currentStatCount then
--print(&quot;BoardChanged to &quot; .. newBoardType .. &quot; with &quot; .. numStats .. &quot; stats&quot;)
rebuildBoard(NewPlayerListGui, newBoardType, numStats)
end
end
local function buildPlayerList()
waitForChild(game, &quot;Players&quot;)
waitForProperty(game.Players, &quot;LocalPlayer&quot;)
local playerListEnabled = testPlayerListPlaces[game.PlaceId] or enablePlayerListGlobally
if localTesting and (game.PlaceId == 0) or (game.PlaceId == -1) then
playerListEnabled = true
end
if not playerListEnabled then
--No playerlist
return
end
supportFriends = testFriendingPlaces[game.PlaceId] or enableFriendingGlobally
if localTesting and (game.PlaceId == 0) or (game.PlaceId == -1) then
supportFriends = false
end
local teams = game:GetService(&quot;Teams&quot;)
if teams then
local teamConnections = {}
teams.ChildAdded:connect(
function(child)
if child:IsA(&quot;Team&quot;) then
teamsChanged()
teamConnections[child] = child.Changed:connect(
function(prop)
if prop == &quot;TeamColor&quot; or prop == &quot;Name&quot; then
--Rebuild when things change
teamsChanged()
end
end)
end
end)
teams.ChildRemoved:connect(
function(child)
if child:IsA(&quot;Team&quot;) then
if teamConnections[child] then
teamConnections[child]:disconnect()
teamConnections[child] = nil
end
teamsChanged()
end
end)
end
game.Players.ChildAdded:connect(
function(player)
if player:IsA(&quot;Player&quot;) then
addPlayerFunction(player)
end
end)
game.Players.ChildRemoved:connect(
function(player)
if player:IsA(&quot;Player&quot;) then
if removePlayerFunction then
removePlayerFunction(player)
end
end
end)
rebuildBoard(NewPlayerListGui, determineBoardType())
delay(0,
function()
while true do
wait(5)
checkIfBoardChanged()
end
end)
end
buildPlayerList()
end </ProtectedString>
<bool name="archivable">true</bool>
</Properties>
</Item>
</Item>
</roblox>