diff --git a/public/asset/11 b/public/asset/11 index d2dcc63..87d19a1 100644 --- a/public/asset/11 +++ b/public/asset/11 @@ -1,1224 +1,178 @@ +%11% +local RbxGui ---new playerlist by Zach Lindblad (fusroblox) ---contact him for any revisions/issues --------------------- --- Super Util --------------------- +local localTesting = true -local ADMINS = -{ - thomas = 1, - morblox = 1, - conkley = 1, - josh = 1, - penguin = 1, - bagofdreams = 1, - template = 1, - AliMine8555 = 1, -} +local screen = script.Parent +local screenResizeCon = nil -local Images = { - bottomDark = '94691904', - bottomLight = '94691940', - midDark = '94691980', - midLight = '94692025', - LargeDark = '96098866', - LargeLight = '96098920', - LargeHeader = '96097470', - NormalHeader = '94692054', - LargeBottom = '96397271', -- '96098152', - NormalBottom = '94754966', - DarkBluePopupMid = '97114905', - LightBluePopupMid = '97114905', - DarkPopupMid = '97112126', - LightPopupMid = '97109338', - DarkBluePopupTop = '97114838', - LightBluePopupTop = '', - DarkPopupTop = '', - LightPopupTop = '', - DarkBluePopupBottom = '97114758', - LightBluePopupBottom = '', - DarkPopupBottom = '100869219', - LightPopupBottom = '97109175', -} +local friendWord = "Friend" +local friendWordLowercase = "friend" +local testFriendingPlaces = {} +testFriendingPlaces[41324860] = true +local enableFriendingGlobally = true ---[[ - Generic object Create function, which I am using to create Gui's - Thanks to Stravant! ---]] -local Obj = {} -function Obj.Create(guiType) - return function(data) - local obj = Instance.new(guiType) - for k, v in pairs(data) do - if type(k) == 'number' then - v.Parent = obj - else - obj[k] = v +local testPlayerListPlaces = {} +testPlayerListPlaces[41324860] = true +testPlayerListPlaces[10042455] = true +local enablePlayerListGlobally = true + +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) + instance.RobloxLocked = true + children = instance:GetChildren() + if children then + for i, child in ipairs(children) do + robloxLock(child) + end + end +end + +function ArrayRemove(t, obj) + for i, obj2 in ipairs(t) do + if obj == obj2 then + table.remove(t, i) + return true + end + end + return false +end + +local function getPlayers() + local result = {} + local players = game:GetService("Players"):GetChildren() + if players then + for i, player in ipairs(players) do + if player:IsA("Player") then + table.insert(result, player) end end - return obj end -end - ---[[ - makes a full sized background for a guiobject - @Args: - imgName asset name of image to fill background - @Return: background gui object ---]] -function MakeBackgroundGuiObj(imgName) - return Obj.Create'ImageLabel' - { - Name = 'Background', - BackgroundTransparency = 1, - Image = imgName, - Position = UDim2.new(0, 0, 0, 0), - Size = UDim2.new(1,0,1,0), - } -end ---[[ turns 255 integer color value to a color3 --]] -function Color3I(r,g,b) - return Color3.new(r/255,g/255,b/255) + return result end ---[[ - Gets correct icon for builder's club status to display by name - @Args: - membershipType Enum of membership status - @Return: string of image asset ---]] -function getMembershipTypeIcon(membershipType,playerName) - if ADMINS[playerName]~=nil then - if ADMINS[playerName] == 1 then - return "rbxasset://textures/ui/TinyAdminIcon.png" - else - return ADMINS[playerName] - end - elseif membershipType == Enum.MembershipType.None then - return "" - elseif membershipType == Enum.MembershipType.BuildersClub then - return "rbxasset://textures/ui/TinyBcIcon.png" - elseif membershipType == Enum.MembershipType.TurboBuildersClub then - return "rbxasset://textures/ui/TinyTbcIcon.png" - elseif membershipType == Enum.MembershipType.OutrageousBuildersClub then - return "rbxasset://textures/ui/TinyObcIcon.png" - else - error("Unknown membershipType" .. membershipType) - end +local brickColorTable = {} +for i = 0, 63 do + brickColorTable[BrickColor.palette(i).Name] = BrickColor.palette(i).Color end -local function getFriendStatusIcon(friendStatus) - if friendStatus == Enum.FriendStatus.Unknown or friendStatus == Enum.FriendStatus.NotFriend then - return "" - elseif friendStatus == Enum.FriendStatus.Friend then - return "http://www.morblox.us/asset/?id=99749771" - elseif friendStatus == Enum.FriendStatus.FriendRequestSent then - return "http://www.morblox.us/asset/?id=99776888" - elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then - return "http://www.morblox.us/asset/?id=99776838" - else - error("Unknown FriendStatus: " .. friendStatus) - 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 ---[[ - Utility function to create buttons for the popup menus - @Args: - nparent what to parent this button to - ntext text to put on this button - index number index of this entry in menu - last is this the last element of the popup menu - @Return: a popup menu button ---]] -function MakePopupButton(nparent,ntext,index,last) - local tobj = Obj.Create"ImageButton" - { - Name = 'ReportButton', - BackgroundTransparency = 1, - Position = UDim2.new(0,0,1*index,0), - Size = UDim2.new(1, 0, 1, 0), - ZIndex=9, - Obj.Create'TextLabel' - { - Name = 'ButtonText', - BackgroundTransparency = 1, - Position = UDim2.new(.07, 0, .07, 0), - Size = UDim2.new(.86,0,.86,0), - Parent = HeaderFrame, - Font = 'ArialBold', - Text = ntext, - FontSize = 'Size14', - TextScaled = true, - TextColor3 = Color3.new(1,1,1), - TextStrokeTransparency = 1, - ZIndex=9, - }, - Parent = nparent, - } - if index==0 then - tobj.Image = 'http://www.morblox.us/asset/?id=97108784' - elseif last then - if index%2==1 then - tobj.Image = 'http://www.morblox.us/asset/?id='.. Images['LightPopupBottom'] - else - tobj.Image = 'http://www.morblox.us/asset/?id='.. Images['DarkPopupBottom'] - end - else - if index%2==1 then - tobj.Image = 'http://www.morblox.us/asset/?id=97112126' - else - tobj.Image = 'http://www.morblox.us/asset/?id=97109338' + +local function getTeams() + local result = {} + local teams = game:GetService("Teams"):GetChildren() + for i, team in ipairs(teams) do + if team:IsA("Team") then + table.insert(result, team) end end - return tobj + return result end +local supportFriends = true +local currentBoardType = "PlayerList" +local currentStatCount = 0 ---[[ - obligatory wait for child function - @Args: - parent Parent object to look for child in - child name of child object to look for - @Return: object waited for ---]] -function WaitForChild(parent,child) - while not parent:FindFirstChild(child) do - wait() debugprint(" child "..parent.Name.." waiting for "..child) - end - return parent[child] -end - - --------------------------- - -- Workspace Objects - --------------------------- - --- might want to move all this to an init function, wait for localplayer elsewhere -local Players = game:GetService('Players') --- make sure this doesn't run on the server(it will if you dont do this) -while not Players.LocalPlayer do - Players.Changed:wait() -end - -local LocalPlayer = Players.LocalPlayer -local Mouse = LocalPlayer:GetMouse() - -local ScreenGui = Obj.Create"Frame" -{ - Name = 'PlayerListScreen', - Size = UDim2.new(1, 0, 1, 0), - BackgroundTransparency = 1, - Parent = script.Parent -- LocalPlayer.PlayerGui -- use for switching into playergui mode -} -local MainFrame = Obj.Create"Frame" -{ - Name = 'LeaderBoardFrame', - Position = UDim2.new(1, -150, 0.005, 0), - Size = UDim2.new(0, 150, 0, 800), - BackgroundTransparency = 1, - Parent = ScreenGui, -} - ---frame used for expanding leaderstats when frame is 'focused' -local FocusFrame = Obj.Create"Frame" -{ - Name = 'FocusFrame', - Position = UDim2.new(0, 0, 0, 0), - Size = UDim2.new(1, 0, 0, 100), - BackgroundTransparency = 1, - Active = true, - Parent = MainFrame, -} - -local TemplateFrameYSize = 0.670000017 - - -- HEADER -local HeaderFrame = Obj.Create"Frame" -{ - Name = 'Header', - BackgroundTransparency = 1, - Position = UDim2.new(0,0,0,0), - Size = UDim2.new(1, 0, .07, 0), - Parent = MainFrame, - MakeBackgroundGuiObj('http://www.morblox.us/asset/?id=94692054'), -} - local HeaderFrameHeight = HeaderFrame.Size.Y.Scale - local MaximizeButton = Obj.Create"ImageButton" - { - Name = 'MaximizeButton', - Active = true, - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 0, 0), - Size = UDim2.new(1,0,1,0), - Parent = HeaderFrame, - } - local HeaderName = Obj.Create"TextLabel" - { - Name = 'PlayerName', - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, .01, 0), - Size = UDim2.new(.98,0,.38,0), - Parent = HeaderFrame, - Font = 'ArialBold', - Text = LocalPlayer.Name, - FontSize='Size24', - --TextScaled = true, - TextColor3 = Color3.new(1,1,1), - TextStrokeColor3 = Color3.new(0,0,0), - TextStrokeTransparency = 0, - TextXAlignment = 'Right', - TextYAlignment = 'Center', - } - local HeaderScore = Obj.Create"TextLabel" - { - Name = 'PlayerScore', - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, .4, 0), - Size = UDim2.new(.98,0,0,30), - Parent = HeaderFrame, - Font = 'ArialBold', - Text = '', - FontSize='Size24', - TextYAlignment = 'Top', - --TextScaled = true, - TextColor3 = Color3.new(1,1,1), - TextStrokeTransparency = 1, - TextXAlignment = 'Right', - TextYAlignment = 'Top', - } - -- BOTTOM - --used for shifting bottom frame for mouse over effects -local BottomShiftFrame = Obj.Create"Frame" -{ - Name= 'BottomShiftFrame', - BackgroundTransparency = 1, - Position = UDim2.new(0,0,HeaderFrameHeight,0), - Size = UDim2.new(1,0,1,0), - Parent=MainFrame, -} - local BottomFrame = Obj.Create"Frame" - { - Name = 'Bottom', - BackgroundTransparency = 1, - Position = UDim2.new(0,0,.07,0), - Size = UDim2.new(1, 0, .03, 0), - Parent = BottomShiftFrame, - MakeBackgroundGuiObj('http://www.morblox.us/asset/?id=94754966'), - } - local ExtendButton = Obj.Create"ImageButton" - { - Name = 'bigbutton', - Active = true, - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 0, 0), - Size = UDim2.new(1,0,1.5,0), - ZIndex = 3, - Parent = BottomFrame, - } - local ExtendTab = Obj.Create"ImageButton" - { - Name = 'extendTab', - Active = true, - BackgroundTransparency = 1, - Image = 'http://www.morblox.us/asset/?id=94692731', - Position = UDim2.new(.608, 0, .3, 0), - Size = UDim2.new(.3,0,.7,0), - Parent = BottomFrame, - } -local TopClipFrame = Obj.Create"Frame" -{ - Name = 'ListFrame', - BackgroundTransparency = 1, - Position = UDim2.new(-1,0,.07,0), - Size = UDim2.new(2, 0, 1, 0), - Parent = MainFrame, - ClipsDescendants = true, -} - local BottomClipFrame = Obj.Create"Frame" - { - Name = 'BottomFrame', - BackgroundTransparency = 1, - Position = UDim2.new(0,0, - .8,0), - Size = UDim2.new(1, 0, 1, 0), - Parent = TopClipFrame, - ClipsDescendants = true, - } - local ScrollBarFrame = Obj.Create"Frame" - { - Name = 'ScrollBarFrame', - BackgroundTransparency = 1, - Position = UDim2.new(.987,0,.8,0), - Size = UDim2.new(.01, 0, .2, 0), - Parent = BottomClipFrame, - } - local ScrollBar = Obj.Create"Frame" - { - Name = 'ScrollBar', - BackgroundTransparency = 0, - BackgroundColor3 = Color3.new(.2,.2,.2), - Position = UDim2.new(0,0,0,0), - Size = UDim2.new(1, 0, .5, 0), - ZIndex = 5, - Parent = ScrollBarFrame, - - } - local ListFrame = Obj.Create"Frame" - { - Name = 'SubFrame', - BackgroundTransparency = 1, - Position = UDim2.new(0,0,.8,0), - Size = UDim2.new(1, 0, 1, 0), - Parent = BottomClipFrame, - } -local PopUpClipFrame = Obj.Create"Frame" -{ - Name = 'PopUpFrame', - BackgroundTransparency = 1, - SizeConstraint='RelativeXX', - Position = MainFrame.Position + UDim2.new( 0,-150,0,0), - Size = UDim2.new(0,150,0,800), - Parent = MainFrame, - ClipsDescendants = true, - ZIndex=9, -} -local PopUpPanel = nil - local PopUpPanelTemplate = Obj.Create"Frame" - { - Name = 'Panel', - BackgroundTransparency = 1, - Position = UDim2.new(1,0,0,0), - Size = UDim2.new(1,0,.032,0), - Parent = PopUpClipFrame, - } - -local StatTitles = Obj.Create"Frame" -{ - Name = 'StatTitles', - BackgroundTransparency = 1, - Position = UDim2.new(0,0,1,-10), - Size = UDim2.new(1, 0, 0, 0), - Parent = HeaderFrame, -} - -local IsMinimized = Instance.new('BoolValue') -local IsMaximized = Instance.new('BoolValue') -local IsTabified = Instance.new('BoolValue') -local AreNamesExpanded = Instance.new('BoolValue') +local createBoardsFunction = nil -local MiddleTemplate = Obj.Create"Frame" -{ - Name = 'MidTemplate', - BackgroundTransparency = 1, - Position = UDim2.new(100,0,.07,0), - Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0), - Obj.Create'ImageLabel' - { - Name = 'BCLabel', - Active = true, - BackgroundTransparency = 1, - Position = UDim2.new(.005, 5, .20, 0), - Size = UDim2.new(0,16,0,16), - SizeConstraint = 'RelativeYY', - Image = "", - ZIndex = 3, - }, - Obj.Create'ImageLabel' - { - Name = 'FriendLabel', - Active = true, - BackgroundTransparency = 1, - Position = UDim2.new(.005, 5, .15, 0), - Size = UDim2.new(0,16,0,16), - SizeConstraint = 'RelativeYY', - Image = "", - ZIndex = 3, - }, - Obj.Create"ImageButton" - { - Name = 'ClickListener', - Active = true, - BackgroundTransparency = 1, - Position = UDim2.new(.005, 1, 0, 0), - Size = UDim2.new(.96,0,1,0), - ZIndex = 3, - }, - Obj.Create"Frame" - { - Name = 'TitleFrame', - BackgroundTransparency = 1, - Position = UDim2.new(.01, 0, 0, 0), - Size = UDim2.new(0,140,1,0), - ClipsDescendants=true, - Obj.Create"TextLabel" - { - Name = 'Title', - BackgroundTransparency = 1, - Position = UDim2.new(0, 5, 0, 0), - Size = UDim2.new(100,0,1,0), - Font = 'Arial', - FontSize='Size14', - TextColor3 = Color3.new(1,1,1), - TextXAlignment = 'Left', - TextYAlignment = 'Center', - ZIndex = 3, - }, - }, - - Obj.Create"TextLabel" - { - Name = 'PlayerScore', - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 0, 0), - Size = UDim2.new(1,0,1,0), - Font = 'ArialBold', - Text = '', - FontSize='Size14', - TextColor3 = Color3.new(1,1,1), - TextXAlignment = 'Left', - TextYAlignment = 'Center', - ZIndex = 3, - }, - --Obj.Create'IntValue'{Name = 'ID'}, - --Obj.Create'ObjectValue'{Name = 'Player'}, - --Obj.Create'IntValue'{Name = 'Score'}, - ZIndex = 3, -} -local MiddleBGTemplate = Obj.Create"Frame" -{ - Name = 'MidBGTemplate', - BackgroundTransparency = 1, - Position = UDim2.new(100,0,.07,0), - Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0), - MakeBackgroundGuiObj('http://www.morblox.us/asset/?id=94692025'), - -} +local playerTable = {} +local teamTable = {} +local teamColorTable = {} - -- REPORT ABUSE OBJECTS - -local ReportAbuseShield = Obj.Create"TextButton" -{ - Name = "ReportAbuseShield", - Text = "", - AutoButtonColor = false, - Active = true, - Visible = true, - Size = UDim2.new(1,0,1,0), - BackgroundColor3 = Color3I(51,51,51), - BorderColor3 = Color3I(27,42,53), - BackgroundTransparency = 1, -} - -local ReportAbuseFrame = Obj.Create "Frame" -{ - Name = "Settings", - Position = UDim2.new(0.5, - 250, 0.5, - 200), - Size = UDim2.new(0.0, 500, 0.0, 400), - BackgroundTransparency = 1, - Active = true, - Parent = ReportAbuseShield, -} - -local AbuseSettingsFrame = Obj.Create"Frame" -{ - Name = "ReportAbuseStyle", - Size = UDim2.new(1, 0, 1, 0), - Active = true, - BackgroundTransparency = 1, - MakeBackgroundGuiObj('http://www.morblox.us/asset/?id=96488767'), -- 96480351'), - Obj.Create"TextLabel" - { - Name = "Title", - Text = "Report Abuse", - TextColor3 = Color3I(221,221,221), - Position = UDim2.new(0.5, 0, 0, 30), - Font = Enum.Font.ArialBold, - FontSize = Enum.FontSize.Size36, - }, - Obj.Create"TextLabel" - { - Name = "Description", - Text = "This will send a complete report to a moderator. The moderator will review the chat log and take appropriate action.", - TextColor3 = Color3I(221,221,221), - Position = UDim2.new(.01, 0, 0, 55), - Size = UDim2.new(.99, 0, 0, 40), - BackgroundTransparency = 1, - Font = Enum.Font.Arial, - FontSize = Enum.FontSize.Size18, - TextWrap = true, - TextXAlignment = Enum.TextXAlignment.Left, - TextYAlignment = Enum.TextYAlignment.Top, - }, - Obj.Create"TextLabel" - { - Name = "AbuseLabel", - Text = "What did they do?", - Font = Enum.Font.Arial, - BackgroundTransparency = 1, - FontSize = Enum.FontSize.Size18, - Position = UDim2.new(0.025,0,0,140), - Size = UDim2.new(0.4,0,0,36), - TextColor3 = Color3I(255,255,255), - TextXAlignment = Enum.TextXAlignment.Left, - }, - Obj.Create"TextLabel" - { - Name = "ShortDescriptionLabel", - Text = "Short Description: (optional)", - Font = Enum.Font.Arial, - FontSize = Enum.FontSize.Size18, - Position = UDim2.new(0.025,0,0,180), - Size = UDim2.new(0.95,0,0,36), - TextColor3 = Color3I(255,255,255), - TextXAlignment = Enum.TextXAlignment.Left, - BackgroundTransparency = 1, - }, - Obj.Create"TextLabel" - { - Name = "ReportingPlayerLabel", - Text = "Reporting Player", - BackgroundTransparency = 1, - Font = Enum.Font.Arial, - FontSize = Enum.FontSize.Size18, - Position = UDim2.new(0.025,0,0,100), - Size = UDim2.new(0.95,0,0,36), - TextColor3 = Color3I(255,255,255), - TextXAlignment = Enum.TextXAlignment.Left, - Parent = AbuseSettingsFrame - }, - - Parent = ReportAbuseFrame, -} - -local AbusePlayerLabel = Obj.Create"TextLabel" -{ - Name = "PlayerLabel", - Text = "", - BackgroundTransparency = 1, - Font = Enum.Font.ArialBold, - FontSize = Enum.FontSize.Size18, - Position = UDim2.new(0.025,0,0,100), - Size = UDim2.new(0.95,0,0,36), - TextColor3 = Color3I(255,255,255), - TextXAlignment = Enum.TextXAlignment.Right, - Parent = AbuseSettingsFrame -} - -local SubmitReportButton = Obj.Create"ImageButton" -{ - Name = "SubmitReportBtn", - Active = false, - BackgroundTransparency = 1, - Position = UDim2.new(.5, - 200, 1, - 80), - Size = UDim2.new(0,150,0,50), - AutoButtonColor = false, - Image = 'http://www.morblox.us/asset/?id=96502438', -- 96501119', - Parent = AbuseSettingsFrame, -} - -local CancelReportButton = Obj.Create"ImageButton" -{ - Name = "CancelBtn", - BackgroundTransparency = 1, - Position = UDim2.new(0.5, 50, 1, - 80), - Size = UDim2.new(0,150,0,50), - AutoButtonColor = true, - Image = 'http://www.morblox.us/asset/?id=96500683', - Parent = AbuseSettingsFrame, -} - -local AbuseDescriptionWrapper = Obj.Create"Frame" -{ - Name = "AbuseDescriptionWrapper", - Position = UDim2.new(0.025,0,0,220), - Size = UDim2.new(0.95,0,1, - 310), - BackgroundColor3 = Color3I(0,0,0), - BorderSizePixel = 0, - Parent = AbuseSettingsFrame, -} - -local AbuseDescriptionBox - -local OriginalAbuseDescriptionBox = Obj.Create"TextBox" -{ - Name = "TextBox", - Text = "", - ClearTextOnFocus = false, - Font = Enum.Font.Arial, - FontSize = Enum.FontSize.Size18, - Position = UDim2.new(0,3,0,3), - Size = UDim2.new(1, - 6,1, - 6), - TextColor3 = Color3I(255,255,255), - TextXAlignment = Enum.TextXAlignment.Left, - TextYAlignment = Enum.TextYAlignment.Top, - TextWrap = true, - BackgroundColor3 = Color3I(0,0,0), - BorderSizePixel = 0, -} - -local CalmingAbuseBox = Obj.Create'Frame' -{ - Name = 'AbuseFeedbackBox', - BackgroundTransparency = 1, - Position=UDim2.new(0.25, 0, 0.300000012, 0), - Size=UDim2.new(0.5, 0, 0.370000005, 0), - MakeBackgroundGuiObj('http://www.morblox.us/asset/?id=96506233'), - Obj.Create'TextLabel' - { - Name = 'Header', - Position=UDim2.new(0,10,.05,0), - Size=UDim2.new(1, -30, .15, 0), - TextScaled = true, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Center, - TextYAlignment = Enum.TextYAlignment.Top, - Text = 'Thanks for your report!', - TextColor3 = Color3.new(1,1,1), - FontSize = Enum.FontSize.Size48, - Font = 'ArialBold', - }, - Obj.Create'TextLabel' - { - Name = 'content', - Position = UDim2.new(0,10,.20,0), - Size = UDim2.new(1, -30, .40, 0), - TextScaled = true, - BackgroundTransparency = 1, - TextColor3 = Color3.new(1,1,1), - Text = 'Our moderators will review the chat logs and determine what happened. The other user is probably just trying to make you mad.\n\nIf anyone used swear words, inappropriate language, or threatened you in real life, please report them for Bad Words or Threats', - TextWrapped = true, - TextYAlignment = Enum.TextYAlignment.Top, - FontSize = Enum.FontSize.Size24, - Font = 'Arial', - }, - Obj.Create'ImageButton' - { - Name = "OkButton", - BackgroundTransparency = 1, - Position = UDim2.new(0.5, -75, 1, -80), - Size = UDim2.new(0,150,0,50), - AutoButtonColor = true, - Image = 'http://www.morblox.us/asset/?id=96507959', - } -} -local NormalAbuseBox = Obj.Create'Frame' -{ - Name = 'AbuseFeedbackBox', - BackgroundTransparency = 1, - Position = UDim2.new(0.25, 0, 0.300000012, 0), - Size = UDim2.new(0.5, 0, 0.370000005, 0), - MakeBackgroundGuiObj('http://www.morblox.us/asset/?id=96506233'), - Obj.Create'TextLabel' - { - Name = 'Header', - Position = UDim2.new(0,10,.05,0), - Size = UDim2.new(1, -30, .15, 0), - TextScaled = true, - BackgroundTransparency = 1, - TextColor3 = Color3.new(1,1,1), - TextXAlignment = Enum.TextXAlignment.Center, - TextYAlignment = Enum.TextYAlignment.Top, - Text = 'Thanks for your report!', - FontSize = Enum.FontSize.Size48, - Font ='ArialBold' - }, - Obj.Create'TextLabel' - { - Name = 'content', - Position = UDim2.new(0,10,.20,0), - Size = UDim2.new(1, -30, .15, 0), - TextScaled = true, - BackgroundTransparency = 1, - TextColor3 = Color3.new(1,1,1), - Text = "Our moderators will review the chat logs and determine what happened.", - TextWrapped = true, - TextYAlignment = Enum.TextYAlignment.Top, - FontSize = Enum.FontSize.Size24, - Font = 'Arial', - }, - Obj.Create'ImageButton' - { - Name = "OkButton", - BackgroundTransparency = 1, - Position = UDim2.new(0.5, -75, 1, -80), - Size = UDim2.new(0,150,0,50), - AutoButtonColor = true, - Image = 'http://www.morblox.us/asset/?id=96507959', - }, -} - -local BigButton=Instance.new('ImageButton') - BigButton.Size=UDim2.new(1,0,1,0) - BigButton.BackgroundTransparency=1 - BigButton.ZIndex=8 - BigButton.Visible=false - --BigButton.Active=false - BigButton.Parent=ScreenGui - - - local debugFrame = Obj.Create"Frame" - { - Name = 'debugframe', - Position = UDim2.new(0, 0, 0, 0), - Size = UDim2.new(0, 150, 0, 800),--0.99000001 - BackgroundTransparency = 1, - - } - local debugplayers = Obj.Create"TextLabel" - { - BackgroundTransparency = .8, - Position = UDim2.new(0, 0, .01, 0), - Size = UDim2.new(1,0,.5,0), - Parent = debugFrame, - Font = 'ArialBold', - Text = '--', - FontSize='Size14', - TextWrapped=true, - TextColor3 = Color3.new(1,1,1), - TextStrokeColor3 = Color3.new(0,0,0), - TextStrokeTransparency = 0, - TextXAlignment = 'Right', - TextYAlignment = 'Center', - } - local debugOutput = Obj.Create"TextLabel" - { - BackgroundTransparency = .8, - Position = UDim2.new(0, 0, .5, 0), - Size = UDim2.new(1,0,.5,0), - Parent = debugFrame, - Font = 'ArialBold', - Text = '--', - FontSize='Size14', - TextWrapped=true, - TextColor3 = Color3.new(1,1,1), - TextStrokeColor3 = Color3.new(0,0,0), - TextStrokeTransparency = 0, - TextXAlignment = 'Right', - TextYAlignment = 'Center', - } - - ---[[ - simple function to toggle the display of debug output ---]] -local DebugPrintEnabled=true -function debugprint(str) - if DebugPrintEnabled then - debugOutput.Text=str +local removePlayerFunction = nil +local recreatePlayerFunction = nil +local addPlayerFunction = function(player) + if recreatePlayerFunction then + recreatePlayerFunction(player) end end +local sortPlayerListsFunction = nil +local minimizedState = nil +local bigWindowImposter = nil +local smallWindowPosition = UDim2.new(0, -20, 0,5) +local smallWindowSize = UDim2.new(1,0,1,0) +local bigWindowSize = UDim2.new(0.6,0,0.6,0) +local bigWindowPosition = UDim2.new(.2, 0, .2,0) - ------------------------- - -- Script objects - ------------------------- -local RbxGui = assert(LoadLibrary('RbxGui')) +local smallWindowHeaderYSize = 32 - -- number of entries to show if you click minimize -local DefaultEntriesOnScreen = 8 +local debounceTeamsChanged = false +local currentWindowState = "Small" +local previousWindowState = nil +local transitionWindowsFunction = nil - +local container = nil +local topRightTrayContainer = nil +local playerContextMenu = nil +local contextMenuElements = {} -for _,i in pairs(Images) do - Game:GetService("ContentProvider"):Preload("http://www.morblox.us/asset/?id="..i) +local function addContextMenuLabel(getText1, getText2, isVisible) + local t = {} + t.Type = "Label" + t.GetText1 = getText1 + t.GetText2 = getText2 + t.IsVisible = isVisible + table.insert(contextMenuElements, t) +end +local function addContextMenuButton(text, isVisible, isActive, doIt) + local t = {} + t.Text = text + t.Type = "Button" + t.IsVisible = isVisible + t.IsActive = isActive + t.DoIt = doIt + table.insert(contextMenuElements, t) end - -- ordered array of 'score data', each entry has: - -- Name(String) - -- Priority(number) - -- IsPrimary (bool, should it be shown in upper right) - -- MaxLength (integer, of the length of the longest element for this column) -local ScoreNames = {} - -- prevents flipping in playerlist panels -local AddId = 0 - -- intermediate table form of all player entries in format of: - -- Frame - -- Player - -- Score - -- ID - -- MyTeam (team ENRTY(not actual team) I am currently on) -local PlayerFrames = {} - -- intermediate ordered frame array, composed of Entrys of - -- Frame - -- MyTeam (my team object) - -- MyPlayers ( an ordered array of all player frames in team ) - -- AutoHide (bool saying whether it should be hidden) - -- IsHidden (bool) - -- ID (int to prevent flipping out of leaderboard, fun times) -local TeamFrames = {} - -- one special entry from teamFrames, for unaffiliated players, only shown if players non - empty -local NeutralTeam = nil - - -- final 'to be displayed' list of frames -local MiddleFrames = {} -local MiddleFrameBackgrounds = {} -local MiddleFrameHeight = .03 - -- time of last click -local LastClick = 0 -local ButtonCooldown = .25 - -local OnIos = false -pcall(function() OnIos = Game:GetService('UserInputService').TouchEnabled end) - - - -- you get 200 of x screen space per stat added, start width 16% -local BaseScreenXSize = 150 -local SpacingPerStat = 10 --spacing between stats - - -local MaximizedBounds = UDim2.new(.5,0,1,0) -local MaximizedPosition = UDim2.new(.25,0,.1,0) -local NormalBounds = UDim2.new(0,BaseScreenXSize, 0, 800) -local NormalPosition = UDim2.new(1 , - BaseScreenXSize, 0.005, 0) - -local MinimizedBounds = UDim2.new(0, BaseScreenXSize, 0.99000001, 0) - - - -- number of stats to show from leaderstats -local NumPrimaryStats = 0 - -- where the scroll par currently is positioned -local ScrollPosition = 0.75999999 -local IsDragging = false -- am I dragging the player list - -local DefaultBottomClipPos = BottomClipFrame.Position.Y.Scale - -local LastSelectedPlayerEntry = nil -local SelectedPlayerEntry = nil -local SelectedPlayer = nil - - -- locks(semaphores) for stopping race conditions -local AddingFrameLock = false -local ChangingOrderLock = false -local AddingStatLock = false -local BaseUpdateLock = false -local WaitForClickLock = false -local InPopupWaitForClick=false -local PlayerChangedLock = false -local NeutralTeamLock = false - -local ScrollWheelConnections = {} - - -local DefaultListSize = 8 -if not OnIos then DefaultListSize = 12 end -local DidMinimizeDrag = false - - -- report abuse objects -local AbuseName -local Abuses = { - "Bad Words or Threats", - "Bad Username", - "Talking about Dating", - "Account Trading or Sharing", - "Asking Personal Questions", - "Rude or Mean Behavior", - "False Reporting Me" -} -local UpdateAbuseFunction -local AbuseDropDown, UpdateAbuseSelection - -local PrivilegeLevel = -{ - Owner = 255, - Admin = 240, - Member = 128, - Visitor = 10, - Banned = 0, -} - - -local IsPersonalServer = not not game.Workspace:FindFirstChild("PSVariable") -if IsPersonalServer then - --THIS SHOULD NOT BE HERE GUYS, only keeping to perserve old functionality - game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager") -end -game.Workspace.ChildAdded:connect(function(nchild) - if nchild.Name=='PSVariable' and nchild:IsA('BoolValue') then - IsPersonalServer=true - --THIS SHOULD NOT BE HERE GUYS, only keeping to perserve old functionality - game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager") - end -end) - ------------------------------- - -- Static Functions - ------------------------------- -function GetTotalEntries() - return math.min(#MiddleFrameBackgrounds,DefaultEntriesOnScreen) -end - -function GetEntryListLength() - local numEnts=#PlayerFrames+#TeamFrames - if NeutralTeam then - numEnts=numEnts+1 - end - return numEnts -end - -function AreAllEntriesOnScreen() - return #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale <= 1 + DefaultBottomClipPos -end - -function GetLengthOfVisbleScroll() - return 1 + DefaultBottomClipPos -end - -function GetMaxScroll() - return DefaultBottomClipPos * - 1 -end - -- can be optimized by caching when this varible changes -function GetMinScroll() - if AreAllEntriesOnScreen() then - return GetMaxScroll() - else - return (GetMaxScroll() - (#MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale)) + (1 + DefaultBottomClipPos) - end -end - -function AbsoluteToPercent(x,y) - return Vector2.new(x,y)/ScreenGui.AbsoluteSize -end ---[[ - tweens text transparency of element from starta to enda over length of time - Warning: should be put in a Spawn call - @Args: - element textobject to tween transparency on - starta alpha to start tweening - enda alpha to end tweening on - length how many seconds to spend tweening ---]] -function TweenTextTransparency(element,starta,enda,length) - local startTime = time() - while time() - startTime < length do - element.TextTransparency = ((enda - starta) * ((time() - startTime)/length)) + starta - wait(.01) - end - element.TextTransparency = enda -end ---[[ - tweens background transparency of element from starta to enda over length of time - Warning: should be put in a Spawn call - @Args: - element guiobject to tween transparency on - starta alpha to start tweening - enda alpha to end tweening on - length how many seconds to spend tweening ---]] -function TweenBackgroundTransparency(element,starta,enda,length) - local startTime = time() - while time() - startTime < length do - element.BackgroundTransparency = ((enda - starta) * ((time() - startTime)/length)) + starta - wait(.01) - end - element.BackgroundTransparency = enda -end - ---[[ - UGLY UGLY HACK FUNCTION - replace with some sort of global input catching A.S.A. FREAKING P. - creates a fullsize gui element to catch next mouse up event(completeing a click) - @Args: - frameParent Object to parent fullscreen gui to - polledFunction function to call on mouse moved events in this gui - exitFunction function to call when click event is fired ---]] -function WaitForClick(frameParent,polledFunction,exitFunction) - if WaitForClickLock then return end - debugprint('waiting for click!') - WaitForClickLock=true - BigButton.Visible=true - --BigButton.Active=true - --BigButton.Parent=frameParent - local upHappened=false - local connection, connection2 - connection2=BigButton.MouseMoved:connect( function(nx,ny) - polledFunction(nx,ny) - end) - connection=BigButton.MouseButton1Up:connect(function(nx,ny) - exitFunction(nx,ny) - BigButton.Visible=false - connection:disconnect() - connection2:disconnect() - debugprint('mouse up!') - end) - frameParent.AncestryChanged:connect(function(child,nparent) - if child == frameParent and nparent ==nil then - exitFunction(nx,ny) - BigButton.Visible=false - connection:disconnect() - connection2:disconnect() - debugprint("forced out of wait for click") - end - end) - WaitForClickLock=false -end - - ---------------------------- ---Personal Server Handling ---------------------------- ---[[ - returns privlage level based on integer rank - Note: these privilege levels seem completely arbitrary, but no documentation exists - this is all from the old player list, really weird - @Args: - rank Integer rank value for player - @Return Normalized integer value for rank? ---]] -function GetPrivilegeType(rank) - if rank <= PrivilegeLevel['Banned'] then - return PrivilegeLevel['Banned'] - elseif rank <= PrivilegeLevel['Visitor'] then - return PrivilegeLevel['Visitor'] - elseif rank <= PrivilegeLevel['Member'] then - return PrivilegeLevel['Member'] - elseif rank <= PrivilegeLevel['Admin'] then - return PrivilegeLevel['Admin'] - else - return PrivilegeLevel['Owner'] - end -end - ---[[ - gives a player a new privilage rank - Note: Very odd that I have to use loops with this instead of directly setting the rank - but no documentation for personal server service exists - @Args: - player player to change rank of - nrank new integer rank to give player ---]] -function SetPrivilegeRank(player,nrank) - while player.PersonalServerRanknrank do - game:GetService("PersonalServerService"):Demote(player) - end -end ---[[ - called when player selects new privilege level from popup menu - @Args: - player player to set privileges on - nlevel new privilege level for this player ---]] -function OnPrivilegeLevelSelect(player,nlevel,BanPlayerButton,VisitorButton,MemberButton,AdminButton) - debugprint('setting privilege level') - SetPrivilegeRank(player,nlevel) - HighlightMyRank(player,BanPlayerButton,VisitorButton,MemberButton,AdminButton) -end - ---[[ - Highlights current rank of this player in the popup menu - @Args: - player Player to check for rank on ---]] -function HighlightMyRank(player,BanPlayerButton,VisitorButton,MemberButton,AdminButton) - BanPlayerButton.Image= 'http://www.morblox.us/asset/?id='..Images['LightPopupMid'] - VisitorButton.Image= 'http://www.morblox.us/asset/?id='..Images['DarkPopupMid'] - MemberButton.Image= 'http://www.morblox.us/asset/?id='..Images['LightPopupMid'] - AdminButton.Image= 'http://www.morblox.us/asset/?id='..Images['DarkPopupBottom'] - - local rank=player.PersonalServerRank - if rank <= PrivilegeLevel['Banned'] then - BanPlayerButton.Image='http://www.morblox.us/asset/?id='..Images['LightBluePopupMid'] - elseif rank <= PrivilegeLevel['Visitor'] then - VisitorButton.Image='http://www.morblox.us/asset/?id='..Images['DarkBluePopupMid'] - elseif rank <= PrivilegeLevel['Member'] then - MemberButton.Image='http://www.morblox.us/asset/?id='..Images['LightBluePopupMid'] - elseif rank <= PrivilegeLevel['Admin'] then - AdminButton.Image= 'http://www.morblox.us/asset/?id='..Images['DarkBluePopupBottom'] - end -end - - -------------------------- - -- Report abuse handling - -------------------------- ---[[ - does final reporting of abuse on selected player, calls closeAbuseDialog ---]] -function OnSubmitAbuse() - if SubmitReportButton.Active then - if AbuseName and SelectedPlayer then - AbuseSettingsFrame.Visible = false - game.Players:ReportAbuse(SelectedPlayer, AbuseName, AbuseDescriptionBox.Text) - if AbuseName == "Rude or Mean Behavior" or AbuseName == "False Reporting Me" then - CalmingAbuseBox.Parent = ReportAbuseShield - else - debugprint('opening abuse box') - NormalAbuseBox.Parent = ReportAbuseShield - end - else - CloseAbuseDialog() - end - end -end - ---[[ - opens the abuse dialog, initialises text to display selectedplayer ---]] -function OpenAbuseDialog() - debugprint('adding report dialog') - AbusePlayerLabel.Text = SelectedPlayer.Name - --AbuseDescriptionBox.Text = "" - PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) - AbuseDescriptionBox=OriginalAbuseDescriptionBox:Clone() - AbuseDescriptionBox.Parent = AbuseDescriptionWrapper - ReportAbuseShield.Parent = ScreenGui -end ---[[ - resets and closes abuse dialog ---]] -function CloseAbuseDialog() - AbuseName = nil - SubmitReportButton.Active = false - SubmitReportButton.Image = 'http://www.morblox.us/asset/?id=96502438' -- 96501119', - AbuseDescriptionBox:Destroy() - CalmingAbuseBox.Parent = nil - NormalAbuseBox.Parent = nil - ReportAbuseShield.Parent = nil - AbuseSettingsFrame.Visible = true -end - ---[[ - creates dropdownbox, registers all listeners for abuse dialog ---]] -function InitReportAbuse() - - UpdateAbuseFunction = function(abuseText) - AbuseName = abuseText - if AbuseName and SelectedPlayer then - SubmitReportButton.Active = true - SubmitReportButton.Image = 'http://www.morblox.us/asset/?id=96501119' - end - end - - AbuseDropDown, UpdateAbuseSelection = RbxGui.CreateDropDownMenu(Abuses, UpdateAbuseFunction, true) - AbuseDropDown.Name = "AbuseComboBox" - AbuseDropDown.Position = UDim2.new(0.425, 0, 0, 142) - AbuseDropDown.Size = UDim2.new(0.55,0,0,32) - AbuseDropDown.Parent = AbuseSettingsFrame - - - CancelReportButton.MouseButton1Click:connect(CloseAbuseDialog) - SubmitReportButton.MouseButton1Click:connect(OnSubmitAbuse) - - CalmingAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog) - NormalAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog) -end - -------------------------------------- --- Friend/unfriending -------------------------------------- ---[[ - gets enum val of friend status, uses pcall for some reason?(from old playerlist) - @Args: - player player object to check if friends with - @Return: enum of friend status ---]] -local function GetFriendStatus(player) +local function getFriendStatus(player) if player == game.Players.LocalPlayer then return Enum.FriendStatus.NotFriend else @@ -1230,1774 +184,1735 @@ local function GetFriendStatus(player) end end end +--Populate the ContextMenus +addContextMenuLabel( + --GetText1 + function(player) + return "Loading..." + end, + --GetText2 + nil, + --IsVisible + function(player) + return getFriendStatus(player) == Enum.FriendStatus.Unknown + end) ---[[ - when friend button is clicked, tries to take appropriate action, - based on current friend status with SelectedPlayer ---]] -function OnFriendButtonSelect() +addContextMenuButton("Send " .. friendWord .. " Request", + --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("Un" .. friendWordLowercase, + --IsVisible + function(player) + return getFriendStatus(player) == Enum.FriendStatus.Friend + end, + --IsActive + function(player) + return true + end, + --DoIt + function(player) + return game.Players.LocalPlayer:RevokeFriendship(player) + end +) +addContextMenuButton("Accept " .. friendWord .. " Request", + --IsVisible + function(player) + return getFriendStatus(player) == Enum.FriendStatus.FriendRequestReceived + end, + --IsActive + function(player) + return true + end, + --DoIt + function(player) + return game.Players.LocalPlayer:RequestFriendship(player) + end +) + +addContextMenuButton("Deny " .. friendWord .. " Request", + --IsVisible + function(player) + return getFriendStatus(player) == Enum.FriendStatus.FriendRequestReceived + end, + --IsActive + function(player) + return true + end, + --DoIt + function(player) + return game.Players.LocalPlayer:RevokeFriendship(player) + end +) + +addContextMenuButton("Cancel " .. friendWord .. " Request", + --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("leaderstats") + if leaderstats then + local stats = {} + local children = leaderstats:GetChildren() + if children then + for i, stat in ipairs(children) do + if stat:IsA("IntValue") then + table.insert(stats, stat.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 friendStatus=GetFriendStatus(SelectedPlayer) - if friendStatus==Enum.FriendStatus.Friend then - LocalPlayer:RevokeFriendship(SelectedPlayer) - elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then - LocalPlayer:RequestFriendship(SelectedPlayer) - elseif friendStatus==Enum.FriendStatus.FriendRequestSent then - LocalPlayer:RevokeFriendship(SelectedPlayer) - elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then - LocalPlayer:RequestFriendship(SelectedPlayer) - end - --PersonalServerPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) - ClosePopUpPanel() - PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) -end + local foundLeaderstats = false + local numStats = 0 + local foundTeam = false -function OnFriendRefuseButtonSelect() + 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 - - LocalPlayer:RevokeFriendship(SelectedPlayer) - ClosePopUpPanel() - PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) -end ------------------------------------- --- Player Entry Handling ------------------------------------- ---[[ - used by lua's table.sort to sort player entries ---]] -function PlayerSortFunction(a,b) - -- prevents flipping out leaderboard - if a['Score'] == b['Score'] then - --return a['ID'] < b['ID'] - return a['Player'].Name:upper() < b['Player'].Name:upper() - end - if not a['Score'] then return false end - if not b['Score'] then return true end - return a['Score'] < b['Score'] -end - - --------------------------------- - -- Stat Handling - --------------------------------- - -- removes and closes all leaderboard stuffs -function BlowThisPopsicleStand() - --ScreenGui:Destroy() - --script:Destroy() - --time to make the fanboys rage... - Tabify() -end ---[[ - used by lua's table.sort to prioritize score entries ---]] -function StatSort(a,b) - -- primary stats should be shown before all others - if a.IsPrimary ~= b.IsPrimary then - return a.IsPrimary - end - -- if priorities are equal, then return the first added one - if a.Priority == b.Priority then - return a.AddId < b.AddId - end - return a.Priority < b.Priority -end ---[[ - doing WAAY too much here, for optimization update only your team - @Args: - playerEntry Entry of player who had a stat change - property Name of stat changed ---]] -function StatChanged(playerEntry,property) - - -- if(playerEntry['MyTeam']) then - -- UpdateSingleTeam(playerEntry['MyTeam']) - -- else - BaseUpdate() - -- end -end ---[[ - Called when stat is added - if playerEntry is localplayer, will add to score names and re-sort the stats, and resize the width of the leaderboard - for all players, will add a listener for if this stat changes - if stat is a string value, crashes the leaderboard - Note:change crash to a 'tabify' leaderboard later - @Args: - nchild new child value to leaderstats - playerEntry entry this stat was added to ---]] -function StatAdded(nchild,playerEntry) - -- dont re - add a leaderstat I alreday have - while AddingStatLock do debugprint('in stat added function lock') wait(1/30) end - AddingStatLock = true - if not (nchild:IsA('StringValue') or nchild:IsA('IntValue') or nchild:IsA('BoolValue') or nchild:IsA('NumberValue') or nchild:IsA('DoubleConstrainedValue') or nchild:IsA('IntConstrainedValue')) then - BlowThisPopsicleStand() + if foundLeaderstats and foundTeam then + return "TeamScore", numStats + elseif foundLeaderstats then + return "PlayerScore", numStats + elseif foundTeam then + return "TeamList", numStats else - local haveScore = false - for _,i in pairs(ScoreNames) do - if i['Name']==nchild.Name then haveScore=true end - end - if not haveScore then - local nstat = {} - nstat['Name'] = nchild.Name - nstat['Priority'] = 0 - if(nchild:FindFirstChild('Priority')) then - nstat['Priority'] = nchild.Priority - end - nstat['IsPrimary'] = false - if(nchild:FindFirstChild('IsPrimary')) then - nstat['IsPrimary'] = true - end - if(nstat['IsPrimary']) then - NumPrimaryStats = NumPrimaryStats + 1 - end - nstat.AddId = AddId - AddId = AddId + 1 - table.insert(ScoreNames,nstat) - table.sort(ScoreNames,StatSort) - UpdateMaximize() - - end - end - AddingStatLock = false - StatChanged(playerEntry) - nchild.Changed:connect(function(property) StatChanged(playerEntry,property) end) - - -end ---[[ - Called when stat is removed from player - for all players, destroys the stat frame associated with this value, - then calls statchanged(to resize frame) - if playerEntry==localplayer, will remove from scorenames - @Args: - nchild ___value to be removed - playerEntry entry of player value is being removed from ---]] -function StatRemoved(nchild,playerEntry) - while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end - AddingStatLock = true - if playerEntry['Frame']:FindFirstChild(nchild.Name) then - debugprint('Destroyed frame!') - playerEntry['Frame'][nchild.Name].Parent = nil - end - if playerEntry['Player'].Name == LocalPlayer.Name then - for i,val in ipairs(ScoreNames) do - if val['IsPrimary'] then - NumPrimaryStats = NumPrimaryStats - 1 - end - if val['Name'] == nchild.Name then - table.remove(ScoreNames,i) - end - end - end - AddingStatLock = false - StatChanged(playerEntry) -end ---[[ - clears all stats from a given playerEntry - used when leaderstats are removed, or when new leaderstats are added(for weird edge case)+ ---]] -function RemoveAllStats(playerEntry) - while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end - AddingStatLock = true - - for i,val in ipairs(ScoreNames) do - if playerEntry['Frame']:FindFirstChild(val['Name']) then - debugprint('Destroyed frame!') - playerEntry['Frame'][val['Name']].Parent = nil - end - if playerEntry['Player'].Name == LocalPlayer.Name then - NumPrimaryStats = NumPrimaryStats - 1 - end - end - if playerEntry['Player'].Name == LocalPlayer.Name then - NumPrimaryStats = NumPrimaryStats - 1 - end - - AddingStatLock = false - StatChanged(playerEntry) -end - - -function GetScoreValue(score) - if score:IsA('DoubleConstrainedValue') or score:IsA('IntConstrainedValue') then - return score.ConstrainedValue - elseif score:IsA('BoolValue') then - if score.Value then return 1 else return 0 end - else - return score.Value + return "PlayerList", numStats end end ---[[ - ---]] -function MakeScoreEntry(entry,scoreval,panel) - if not panel:FindFirstChild('PlayerScore') then return end - local nscoretxt = panel:FindFirstChild('PlayerScore'):Clone() - local thisScore = nil - --here lies the resting place of a once great and terrible bug - --may its treachery never be forgoten, lest its survivors fall for it again - --RIP the leaderstat bug, oct 2012-nov 2012 - wait() - if entry['Player']:FindFirstChild('leaderstats') then - thisScore = entry['Player']:FindFirstChild('leaderstats'):FindFirstChild(scoreval['Name']) - else + +local function toggleBigWindow() + if container == nil then return end - - if not entry['Player'].Parent then return end - - nscoretxt.Name = scoreval['Name'] - nscoretxt.Text = tostring(GetScoreValue(thisScore)) - if scoreval['Name'] == ScoreNames[1]['Name'] then - debugprint('changing score') - entry['Score'] = GetScoreValue(thisScore) - if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end - end - thisScore.Changed:connect(function() - if not thisScore.Parent then return end - if scoreval['Name'] == ScoreNames[1]['Name'] then - - entry['Score'] = GetScoreValue(thisScore) - if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end - end - nscoretxt.Text = tostring(GetScoreValue(thisScore)) - BaseUpdate() - end) - return nscoretxt - -end - -function CreateStatTitle(statName) - - local ntitle = MiddleTemplate:FindFirstChild('PlayerScore'):Clone() - ntitle.Name = statName - ntitle.Text = statName - -- ntitle - if IsMaximized.Value then - ntitle.TextTransparency = 0 - else - ntitle.TextTransparency = 1 - end - ntitle.Parent = StatTitles -end - -function RecreateScoreColumns(ptable) - while AddingStatLock do debugprint ('In Adding Stat Lock2') wait(1/30) end - AddingStatLock = true - local Xoffset=BaseScreenXSize --current offset from left - local maxXOffset=Xoffset - local MaxSizeColumn=0 --max size for this column - - -- foreach known leaderstat - for j = 1, #ScoreNames,1 do - local scoreval = ScoreNames[j] - --if scoreval['ColumnSize'] then - -- MaxSizeColumn=0--scoreval['ColumnSize'] - --else - MaxSizeColumn=0 - --end - -- for each entry in this player table - for i,entry in ipairs(ptable) do - local panel = entry['Frame'] - local tplayer = entry['Player'] - -- if this panel does not have an element named after this stat - if not panel:FindFirstChild(scoreval['Name']) then - -- make an entry for this object - local nentry = MakeScoreEntry(entry,scoreval,panel) - if nentry then - debugprint('adding '..nentry.Name..' to '..entry['Player'].Name ) - nentry.Parent = panel - -- add score to team - if entry['MyTeam'] and entry['MyTeam'] ~= NeutralTeam and not entry['MyTeam']['Frame']:FindFirstChild(scoreval['Name']) then - local ntitle = nentry:Clone() - ntitle.Parent = entry['MyTeam']['Frame'] - end - - end - end - scoreval['XOffset']=Xoffset - - if panel:FindFirstChild(scoreval['Name']) then - MaxSizeColumn=math.max(MaxSizeColumn,panel[scoreval['Name']].TextBounds.X) - end - end - -- add stat title to top bar - if not StatTitles:FindFirstChild(scoreval['Name']) then - CreateStatTitle(scoreval['Name']) - end - - if AreNamesExpanded.Value then - MaxSizeColumn=math.max(MaxSizeColumn,StatTitles[scoreval['Name'] ].TextBounds.X) - StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(0,Xoffset,0,0),'Out','Quad',.25,true) + if currentWindowState == "Big" then + --Hide it + if previousWindowState == nil or previousWindowState == "Big" or previousWindowState == "None" then + transitionWindowsFunction("None") else - StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0),'Out','Quad',.25,true) + transitionWindowsFunction("Small") end - scoreval['ColumnSize']=MaxSizeColumn - Xoffset= Xoffset+SpacingPerStat+MaxSizeColumn - maxXOffset=math.max(Xoffset,maxXOffset) - end - --print(maxXOffset) - NormalBounds = UDim2.new(0, maxXOffset,0,800) - NormalPosition = UDim2.new(1 , -NormalBounds.X.Offset, NormalPosition.Y.Scale, 0) - UpdateHeaderNameSize() - UpdateMaximize() - - AddingStatLock = false -end - --------------------------- - -- Minimizing and maximizing - --------------------------- - -function ToggleMinimize() - IsMinimized.Value = not IsMinimized.Value - UpdateStatNames() -end - -function ToggleMaximize() - IsMaximized.Value = not IsMaximized.Value - RecreateScoreColumns(PlayerFrames) --done to re-position stat names NOTE: optimize-able -end - -function Tabify() - IsTabified.Value= true - IsMaximized.Value=false - IsMinimized.Value=true - UpdateMinimize() - IsTabified.Value= true - ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Quad',1,true) -end - -function UnTabify() - if IsTabified.Value then - IsTabified.Value= false - ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Quad',1,true) - end -end - ---[[ - Does more than it looks like - monitors positions of the clipping frames and bottom frames - called from EVERYWHERE, too much probably ---]] -function UpdateMinimize() - - if IsMinimized.Value then - if IsMaximized.Value then - ToggleMaximize() - end - if not IsTabified.Value then - MainFrame:TweenSizeAndPosition(UDim2.new(0.010, HeaderName.TextBounds.X, NormalBounds.Y.Scale,NormalBounds.Y.Offset), - UDim2.new(.990, -HeaderName.TextBounds.X, NormalPosition.Y.Scale,0),'Out','Quad',1,true) - else - MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true) - end - --(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale) - BottomClipFrame:TweenPosition(UDim2.new(0,0,-1,0), "Out", "Linear", .25,true) - BottomFrame:TweenPosition(UDim2.new(0,0,0,0), "Out", "Linear", .25,true) - FocusFrame.Size=UDim2.new(1,0,HeaderFrameHeight,0) - ExtendTab.Image = 'http://www.morblox.us/asset/?id=94692731' else - if not IsMaximized.Value then - MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true) - end - --do limiting - DefaultBottomClipPos = math.min(math.max(DefaultBottomClipPos,-1),-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale)) - UpdateScrollPosition() - -- - --BottomClipFrame:TweenPosition(UDim2.new(0,0,DefaultBottomClipPos,0), "Out", "Linear", .25,true) - BottomClipFrame.Position=UDim2.new(0,0,DefaultBottomClipPos,0) - --BottomFrame:TweenPosition(UDim2.new(0,0,((GetTotalEntries()) * MiddleTemplate.Size.Y.Scale),0), "Out", "Linear", .25,true) - local bottomPositon = (DefaultBottomClipPos+BottomClipFrame.Size.Y.Scale) - --BottomFrame:TweenPosition(UDim2.new(0,0,bottomPositon,0), "Out", "Linear", .25,true) - BottomFrame.Position=UDim2.new(0,0,bottomPositon,0) - FocusFrame.Size=UDim2.new(1,0,bottomPositon + HeaderFrameHeight,0) - ExtendTab.Image = 'http://www.morblox.us/asset/?id=94825585' --wat, why did I put this here? - - - + previousWindowState = currentWindowState + transitionWindowsFunction("Big") end end - ---[[ - Manages the position/size of the mainFrame, swaps out different resolution images for the frame - fades in and out the stat names, moves position of headername and header score ---]] -function UpdateMaximize() - if IsMaximized.Value then - for j = 1, #ScoreNames,1 do - local scoreval = ScoreNames[j] - StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0),'Out','Quad',.25,true) +local previousBigPlayerList = nil +local function rebuildBoard(owner, boardType, numStats) + if topRightTrayContainer == nil then + topRightTrayContainer = owner:FindFirstChild("PlayerListTopRightFrame") + if topRightTrayContainer == nil then + topRightTrayContainer = Instance.new("Frame") + topRightTrayContainer.Name = "PlayerListTopRightFrame" + topRightTrayContainer.BackgroundTransparency = 1 + topRightTrayContainer.Size = UDim2.new(0.2, 16, 0.42, 16) + topRightTrayContainer.Position = UDim2.new(0.8, 0, 0, 0) + topRightTrayContainer.Parent = container end + end + if minimizedState == nil then + minimizedState = Instance.new("Frame") + minimizedState.Name = "MinimizedPlayerlist" + minimizedState.BackgroundTransparency = 1 + minimizedState.Position = UDim2.new(1, -166, 0,0) + minimizedState.Size = UDim2.new(0, 151, 0, 30) - if IsMinimized.Value then - ToggleMinimize() + playerListButton = Instance.new("ImageButton") + playerListButton.Name = "GoSmallButton" + playerListButton.Image = "rbxasset://textures/ui/playerlist_hidden_small.png" + playerListButton.BackgroundTransparency = 1 + playerListButton.Size = UDim2.new(0.0, 35, 0, 30) + playerListButton.Position = UDim2.new(1, -35, 0, 0) + playerListButton.MouseButton1Click:connect( + function() + transitionWindowsFunction("Small") + end) + playerListButton.Parent = minimizedState + + minimizedState.Visible = false + robloxLock(minimizedState) + minimizedState.Parent = topRightTrayContainer + end + if bigWindowImposter == nil then + bigWindowImposter = owner:FindFirstChild("BigPlayerListWindowImposter") + if bigWindowImposter == nil then + bigWindowImposter = Instance.new("Frame") + bigWindowImposter.Name = "BigPlayerListWindowImposter" + bigWindowImposter.Visible = false + bigWindowImposter.BackgroundColor3 = Color3.new(0,0,0) + bigWindowImposter.BackgroundTransparency = 0.7 + bigWindowImposter.BorderSizePixel = 0 + bigWindowImposter.Size = UDim2.new(0.4, 7, 0.4, 7) + bigWindowImposter.Position = UDim2.new(0.3, 0, 0.3, 0) + robloxLock(bigWindowImposter) + bigWindowImposter.Parent = container + end + end + if container == nil or container ~= owner then + container = owner + + topRightTrayContainer.Parent = container + bigWindowImposter.Parent = container + end + + local smallVisible = true + local bigVisible = false + if container then + if topRightTrayContainer then + --Delete the old boards + if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then + smallVisible = topRightTrayContainer.SmallPlayerlist.Visible + topRightTrayContainer.SmallPlayerlist.Parent = nil + end + end + if container:FindFirstChild("BigPlayerlist") then + bigVisible = container.BigPlayerlist.Visible or (previousBigPlayerList ~= nil) + container.BigPlayerlist.Parent = nil + if previousBigPlayerList ~= nil then + pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) + previousBigPlayerList = nil + end + end + end + + local smallBoard, bigBoard = createBoardsFunction(boardType, numStats) + if smallBoard then + smallBoard.Visible = smallVisible + smallBoard.Parent = topRightTrayContainer + recalculateSmallPlayerListSize(smallBoard) + end + if bigBoard then + if bigVisible then + previousBigPlayerList = bigBoard + local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(previousBigPlayerList, Enum.CenterDialogType.PlayerInitiatedDialog, + function() + previousBigPlayerList.Visible = true + end) + end) + bigBoard.Visible = bigVisible else - UpdateMinimize() - end - - - MainFrame:TweenSizeAndPosition(MaximizedBounds,MaximizedPosition,'Out','Quad',1,true) - HeaderScore:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true) - HeaderName:TweenPosition(UDim2.new( - .1, - HeaderScore.TextBounds.x,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true) - HeaderFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['LargeHeader'] - BottomFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['LargeBottom'] - for index, i in ipairs(MiddleFrameBackgrounds) do - if (index%2) ~= 1 then - i.Background.Image = 'http://www.morblox.us/asset/?id='..Images['LargeDark'] - else - i.Background.Image = 'http://www.morblox.us/asset/?id='..Images['LargeLight'] - end - end - for index, i in ipairs(MiddleFrames) do - if i:FindFirstChild('ClickListener') then - i.ClickListener.Size = UDim2.new(.974,0,i.ClickListener.Size.Y.Scale,0) - end - for j=1, #ScoreNames,1 do - local scoreval = ScoreNames[j] - if i:FindFirstChild(scoreval['Name']) then - i[scoreval['Name']]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1)),0,0,0), "Out", "Linear", .25,true) - end - end - end - for i,entry in ipairs(PlayerFrames) do - WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0) - end - - for i,entry in ipairs(TeamFrames) do - WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0) - end - - else - if not IsMinimized.Value then - MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Quad',1,true) - end - HeaderScore:TweenPosition(UDim2.new(0,0,.4,0), "Out", "Linear", .25,true) - HeaderName:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", .25,true) - HeaderFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['NormalHeader'] - BottomFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['NormalBottom'] - for index, i in ipairs(MiddleFrameBackgrounds) do - if index%2 ~= 1 then - i.Background.Image = 'http://www.morblox.us/asset/?id='..Images['midDark'] - else - i.Background.Image = 'http://www.morblox.us/asset/?id='..Images['midLight'] - end - end - for index, i in ipairs(MiddleFrames) do - if i:FindFirstChild('ClickListener') then - i.ClickListener.Size = UDim2.new(.96,0,i.ClickListener.Size.Y.Scale,0) - for j=1, #ScoreNames,1 do - local scoreval = ScoreNames[j] - --print(scoreval['XOffset']) - if i:FindFirstChild(scoreval['Name']) and scoreval['XOffset'] then - --print('updateing stat position: ' .. scoreval['Name']) - i[scoreval['Name']]:TweenPosition(UDim2.new(0,scoreval['XOffset'],0,0), "Out", "Linear", .25,true) - end - end - end - end - - for i,entry in ipairs(TeamFrames) do - WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0) - - end - for i,entry in ipairs(PlayerFrames) do - WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0) + bigBoard.Visible = false end + bigBoard.Parent = container end + return container end -function UpdateStatNames() - if not AreNamesExpanded.Value or IsMinimized.Value then - CloseNames() - else - ExpandNames() +function recalculateSmallPlayerListSize(smallPlayerList) + waitForChild(smallPlayerList,"ScrollingArea") + waitForChild(smallPlayerList.ScrollingArea, "ScrollingFrame") + local scrollingFrame = smallPlayerList.ScrollingArea.ScrollingFrame + local playerLines = scrollingFrame:GetChildren() + + local totalPlayerListSize = 0 + for i = 1, #playerLines do + totalPlayerListSize = totalPlayerListSize + playerLines[i].AbsoluteSize.Y end -end -function ExpandNames() - --print('enered expand names') - if #ScoreNames ~= 0 then - for _,i in pairs(StatTitles:GetChildren()) do - --print (tostring(#ScoreNames) .. " is expanding") - Spawn(function()TweenTextTransparency(i,i.TextTransparency,0,.25) end) - end - HeaderFrameHeight=.09 - --as of writing, this and 'CloseNames' are the only places headerframe is resized - HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0), - HeaderFrame.Position,'Out','Quad',.25,true) - TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Quad',.25,true) - BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Quad', .25,true) - - end - -end - -function CloseNames() - --print('close names called') - if #ScoreNames ~= 0 then - HeaderFrameHeight=.07 - if not (IsMaximized.Value) then - for _,i in pairs(StatTitles:GetChildren()) do - Spawn(function()TweenTextTransparency(i,i.TextTransparency,1,.25) end) - end - end - BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Quad', .25,true) - HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0), - HeaderFrame.Position,'Out','Quad',.25,true) - TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Quad',.25,true) - end -end - -function OnScrollWheelMove(direction) - if not (IsTabified.Value or IsMinimized.Value or InPopupWaitForClick) then - local StartFrame = ListFrame.Position - local newFrameY = math.max(math.min(StartFrame.Y.Scale + (direction),GetMaxScroll()),GetMinScroll()) - - ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset) - UpdateScrollPosition() - end -end - -function AttachScrollWheel() - if ScrollWheelConnections then return end - local pmouse = LocalPlayer:GetMouse() - ScrollWheelConnections = {} - table.insert(ScrollWheelConnections,pmouse.WheelForward:connect(function() - OnScrollWheelMove(.05) - end)) - table.insert(ScrollWheelConnections,pmouse.WheelBackward:connect(function() - OnScrollWheelMove(-.05) - end)) -end - -function DetachScrollWheel() - if ScrollWheelConnections then - for _,i in pairs(ScrollWheelConnections) do - i:disconnect() - end - end - ScrollWheelConnections=nil -end - -FocusFrame.MouseEnter:connect(function() - if not (IsMinimized.Value or IsTabified.Value) then - AttachScrollWheel() - end -end) -FocusFrame.MouseLeave:connect(function() - --if not (IsMaximized.Value or IsMinimized.Value) then - DetachScrollWheel() - --end -end) - - ------------------------ - -- Scroll Bar functions - ------------------------ ---[[ - updates whether the scroll bar should be showing, if it is showing, updates - the size of it ---]] -function UpdateScrollBarVisibility() - if AreAllEntriesOnScreen() then - ScrollBar.BackgroundTransparency = 1 - else - ScrollBar.BackgroundTransparency = 0 - UpdateScrollBarSize() - end -end ---[[ - updates size of scrollbar depending on how many entries exist ---]] -function UpdateScrollBarSize() - local entryListSize = #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale - local shownAreaSize = ((BottomClipFrame.Position.Y.Scale) + 1) - ScrollBar.Size = UDim2.new(1,0,shownAreaSize/entryListSize,0) - -end ---[[ - updates position of listframe so that no gaps at the bottom or top of the list are visible - updates position of scrollbar to match what parts of the list are visible ---]] -function UpdateScrollPosition() - local minPos = GetMinScroll() - local maxPos = GetMaxScroll() - local scrollLength = maxPos - minPos - - local yscrollpos=math.max(math.min(ListFrame.Position.Y.Scale,maxPos),minPos) - ListFrame.Position=UDim2.new(ListFrame.Position.X.Scale,ListFrame.Position.X.Offset,yscrollpos,ListFrame.Position.Y.Offset) - - local adjustedLength = 1 - ScrollBar.Size.Y.Scale - ScrollBar.Position = UDim2.new(0,0,adjustedLength - (adjustedLength * ((ListFrame.Position.Y.Scale - minPos)/scrollLength)),0) -end - ---[[ - WARNING:this is in a working state, but uses massive hacks - revize when global input is available - Manages scrolling of the playerlist on mouse drag ---]] -function StartDrag() - Delay(0,function() - debugprint('Got Click') - local stopDrag = false - local function dragExit() - debugprint('undone click') - stopDrag = true - end - local startY = nil --AbsoluteToPercent(Mouse.X,Mouse.Y).Y - local StartFrame = ListFrame.Position - local function dragpoll(nx,ny) - if not startY then - startY = AbsoluteToPercent(nx,ny).Y - end - local nowY = AbsoluteToPercent(nx,ny).Y - local newFrameY - if OnIos then - newFrameY = math.max(math.min(StartFrame.Y.Scale + (nowY - startY),GetMaxScroll()),GetMinScroll()) - else - newFrameY = math.max(math.min(StartFrame.Y.Scale - (nowY - startY),GetMaxScroll()),GetMinScroll()) - end - ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset) - UpdateScrollPosition() - end - Spawn(function() WaitForClick(ScreenGui,dragpoll,dragExit) end) - end) + local yOffset = math.max(0,(smallPlayerList.Size.Y.Scale * smallPlayerList.Parent.AbsoluteSize.Y) - totalPlayerListSize - smallWindowHeaderYSize) + smallPlayerList.Size = UDim2.new(smallPlayerList.Size.X.Scale,smallPlayerList.Size.X.Offset,smallPlayerList.Size.Y.Scale,-yOffset) end -function StartMinimizeDrag() - Delay(0,function() - local startTime=tick() - debugprint('Got Click2') - local stopDrag = false - local function dragExit() - debugprint('undone click2') - if tick()-startTime<.25 then --was click - ToggleMinimize() - else --was drag - DidMinimizeDrag = true - if IsMinimized.Value then - ToggleMinimize() - end - end - stopDrag = true - end - local startY = nil - local StartFrame = DefaultBottomClipPos - local function dragpoll(nx,ny) - if not IsMinimized.Value then - - if not startY then - startY = AbsoluteToPercent(nx,ny).Y - end - local nowY = AbsoluteToPercent(nx,ny).Y - local newFrameY - newFrameY = math.min(math.max(StartFrame + (nowY - startY),-1),-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale)) - DefaultBottomClipPos = newFrameY - UpdateMinimize() - ScrollBarFrame.Size= UDim2.new(ScrollBarFrame.Size.X.Scale,0,(DefaultBottomClipPos+BottomClipFrame.Size.Y.Scale),0) - ScrollBarFrame.Position= UDim2.new(ScrollBarFrame.Position.X.Scale,0,1-ScrollBarFrame.Size.Y.Scale,0) - UpdateScrollBarSize() - UpdateScrollPosition() - UpdateScrollBarVisibility() - - end - end - Spawn(function() WaitForClick(ScreenGui,dragpoll,dragExit) end) - end) - -end - - ------------------------------- - -- Input Callback functions - ------------------------------- -IsMaximized.Value=false -IsMinimized.Value=false -IsMaximized.Changed:connect(UpdateMaximize) -IsMinimized.Changed:connect(UpdateMinimize) - -ExtendButton.MouseButton1Down:connect(function() - if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end - LastClick = time() - if IsTabified.Value then - UnTabify() - else - StartMinimizeDrag() - end -end) - -MaximizeButton.MouseButton1Click:connect(function() - if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end - LastClick = time() - if IsTabified.Value then - UnTabify() - elseif not AreNamesExpanded.Value then - AreNamesExpanded.Value = true - BaseUpdate() - else - ToggleMaximize() - end -end) - -MaximizeButton.MouseButton2Click:connect(function() - if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end - LastClick = time() - if IsTabified.Value then - UnTabify() - elseif IsMaximized.Value then - ToggleMaximize() - elseif AreNamesExpanded.Value then - AreNamesExpanded.Value = false - BaseUpdate() - else - Tabify() - end -end) - - -------------------------------- --- MiddleFrames management -------------------------------- ---[[ - adds a background frame to the listframe ---]] -function AddMiddleBGFrame() - local nBGFrame = MiddleBGTemplate:Clone() - nBGFrame.Position = UDim2.new(.5,0,((#MiddleFrameBackgrounds) * nBGFrame.Size.Y.Scale),0) - if (#MiddleFrameBackgrounds+1)%2 ~= 1 then - if IsMaximized.Value then - nBGFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['LargeDark'] - else - nBGFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['midDark'] - end - else - if IsMaximized.Value then - nBGFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['LargeLight'] - else - nBGFrame.Background.Image = 'http://www.morblox.us/asset/?id='..Images['midLight'] - end - end - nBGFrame.Parent = ListFrame - table.insert(MiddleFrameBackgrounds,nBGFrame) - - if #MiddleFrameBackgrounds 1 do - fSize=fSize-1 - tHeader.FontSize=FONT_SIZES[fSize] - wait(.2) - end - HeaderName.FontSize=tHeader.FontSize - tHeader:Destroy() - end) -end -ScreenGui.Changed:connect(UpdateHeaderNameSize) - ---[[ - called only when the leaderstats object is added to a given player entry - removes old stats, adds any existing stats, and sets up listeners for new stats - @Args: - playerEntry A reference to the ENTRY(table) of the player who had leaderstats added ---]] -function LeaderstatsAdded(playerEntry) - --RemoveAllStats(playerEntry) - local nplayer = playerEntry['Player'] - for _,i in pairs(nplayer.leaderstats:GetChildren()) do - StatAdded(i,playerEntry) - end - nplayer.leaderstats.ChildAdded:connect(function(nchild) StatAdded(nchild,playerEntry) end) - nplayer.leaderstats.ChildRemoved:connect(function(nchild) StatRemoved(nchild,playerEntry) end) -end ---[[ - called when leaderstats object is removed from play in player entry - Note: may not be needed, might be able to just rely on leaderstats added - @Args: - oldLeaderstats leaderstats object to be removed - playerEntry A reference to the ENTRY(table) of the player ---]] -function LeaderstatsRemoved(oldLeaderstats,playerEntry) - while AddingFrameLock do debugprint('waiting to insert '..playerEntry['Player'].Name) wait(1/30) end - AddingFrameLock = true - RemoveAllStats(playerEntry) - AddingFrameLock = false -end - -function ClosePopUpPanel() - if SelectedPlayerEntry then --on random times this will be called by both button and playermouse - local tframe = SelectedPlayerEntry['Frame'] - Spawn(function() TweenBackgroundTransparency(tframe,.5,1,.25) end) - PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) - wait(.1) - InPopupWaitForClick= false - SelectedPlayerEntry = nil - end - -end - ---[[ - prepares the needed popup to be tweened on screen, and updates the position of the popup clip - frame to match the selected player frame's position ---]] -function InitMovingPanel( entry, player) - PopUpClipFrame.Parent= ScreenGui - - if PopUpPanel then - PopUpPanel:Destroy() - end - PopUpPanel= PopUpPanelTemplate:Clone() - PopUpPanel.Parent= PopUpClipFrame - - local nextIndex = 2 - local friendStatus = GetFriendStatus(player) - local showRankMenu = IsPersonalServer and LocalPlayer.PersonalServerRank >= PrivilegeLevel['Admin'] and LocalPlayer.PersonalServerRank > SelectedPlayer.PersonalServerRank - - - local ReportPlayerButton = MakePopupButton(PopUpPanel,'Report Player',0) - ReportPlayerButton.MouseButton1Click:connect(function() ClosePopUpPanel() OpenAbuseDialog() end) - local FriendPlayerButton = MakePopupButton(PopUpPanel,'Friend',1, not showRankMenu and friendStatus~=Enum.FriendStatus.FriendRequestReceived) - FriendPlayerButton.MouseButton1Click:connect(OnFriendButtonSelect) - - - if friendStatus==Enum.FriendStatus.Friend then - FriendPlayerButton:FindFirstChild('ButtonText').Text='UnFriend Player' - elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then - FriendPlayerButton:FindFirstChild('ButtonText').Text='Send Request' - elseif friendStatus==Enum.FriendStatus.FriendRequestSent then - FriendPlayerButton:FindFirstChild('ButtonText').Text='Revoke Request' - elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then - FriendPlayerButton:FindFirstChild('ButtonText').Text='Accept Friend' - local FriendRefuseButton = MakePopupButton(PopUpPanel,'Decline Friend',2,not showRankMenu) - FriendRefuseButton.MouseButton1Click:connect(OnFriendRefuseButtonSelect) - nextIndex=nextIndex+1 - end - - if showRankMenu then - local BanPlayerButton = MakePopupButton(PopUpPanel,'Ban',nextIndex) - local VisitorButton = MakePopupButton(PopUpPanel,'Visitor',nextIndex+1) - local MemberButton = MakePopupButton(PopUpPanel,'Member',nextIndex+2) - local AdminButton = MakePopupButton(PopUpPanel,'Admin',nextIndex+3,true) - - BanPlayerButton.MouseButton1Click:connect(function() ClosePopUpPanel() - OnPrivilegeLevelSelect(player,PrivilegeLevel['Banned'],BanPlayerButton,VisitorButton,MemberButton,AdminButton) - end) - VisitorButton.MouseButton1Click:connect(function() ClosePopUpPanel() - OnPrivilegeLevelSelect(player,PrivilegeLevel['Visitor'],BanPlayerButton,VisitorButton,MemberButton,AdminButton) - end) - MemberButton.MouseButton1Click:connect(function() ClosePopUpPanel() - OnPrivilegeLevelSelect(player,PrivilegeLevel['Member'],BanPlayerButton,VisitorButton,MemberButton,AdminButton) - end) - AdminButton.MouseButton1Click:connect(function() ClosePopUpPanel() - OnPrivilegeLevelSelect(player,PrivilegeLevel['Admin'],BanPlayerButton,VisitorButton,MemberButton,AdminButton) - end) - - HighlightMyRank(SelectedPlayer,BanPlayerButton,VisitorButton,MemberButton,AdminButton) - end - - PopUpPanel:TweenPosition(UDim2.new(0,0,0,0), "Out", "Quad", .5,true) - Delay(1, function() - local tconnection - tconnection = LocalPlayer:GetMouse().Button1Down:connect(function() - tconnection:disconnect() - ClosePopUpPanel() - end) - end) - - local myFrame = entry['Frame'] - -- THIS IS GARBAGE. - -- if I parent to frame to auto update position, it gets clipped - -- sometimes garbage is the only option. - Spawn(function() - --print('got in spawn') - while InPopupWaitForClick do - --print('in position update loop') - PopUpClipFrame.Position=UDim2.new( 0,myFrame.AbsolutePosition.X-PopUpClipFrame.Size.X.Offset,0,myFrame.AbsolutePosition.Y) - wait() - end - end) - -end - ---[[ - Called when a player entry in the leaderboard is clicked - either will highlight entry and start the drag event, or open a popup menu - @Args: - entry the player entry clicked ---]] -function OnPlayerEntrySelect(entry) - if SelectedPlayer then - debugprint('trying to open popup menu!!'.. tostring(entry == SelectedPlayerEntry).. ' ' .. tostring(SelectedPlayer~=LocalPlayer)..' ' .. tostring(SelectedPlayer.userId) ..' '..tostring(LocalPlayer.userId) ) - end - if not InPopupWaitForClick and entry == SelectedPlayerEntry and SelectedPlayer~=LocalPlayer and SelectedPlayer and SelectedPlayer.userId>1 and LocalPlayer.userId>1 then - - entry['Frame'].BackgroundColor3 = Color3.new(0,1,1) - Spawn(function() TweenBackgroundTransparency(entry['Frame'],1,.5,.5) end) - InPopupWaitForClick=true - InitMovingPanel(entry,SelectedPlayer) - - - elseif not InPopupWaitForClick then - --print('starting drag ', entry['Player'].Name) - --movingPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true) - SelectedPlayerEntry = entry - SelectedPlayer = entry['Player'] - - Delay(1, function() - if not InPopupWaitForClick then - SelectedPlayerEntry = nil - end - end) - StartDrag() - end - - -end - ---[[ - the basic update for the playerlist mode's state, - assures the order and length of the player frames ---]] -function PlayerListModeUpdate() - RecreateScoreColumns(PlayerFrames) - table.sort(PlayerFrames,PlayerSortFunction) - for i,val in ipairs(PlayerFrames) do - MiddleFrames[i] = val['Frame'] - end - for i = #PlayerFrames + 1,#MiddleFrames,1 do - MiddleFrames[i] = nil - end - UpdateMinimize() -end ---[[ - this one's a doozie, happens when a player is added to the game - inits their player frame and player entry, assigns them to a team if possible, - and hooks up their leaderstats - @Args: - nplayer new player object to insert ---]] -function InsertPlayerFrame(nplayer) - while AddingFrameLock do debugprint('waiting to insert '..nplayer.Name) wait(1/30) end - AddingFrameLock = true - - local nFrame = MiddleTemplate:Clone() - WaitForChild(WaitForChild(nFrame,'TitleFrame'),'Title').Text = nplayer.Name - - nFrame.Position = UDim2.new(1,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0) - - local nfriendstatus = GetFriendStatus(nplayer) - - nFrame:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(nplayer.MembershipType,nplayer.Name) - nFrame:FindFirstChild('FriendLabel').Image = getFriendStatusIcon(nfriendstatus) - nFrame.Name = nplayer.Name - WaitForChild(WaitForChild(nFrame,'TitleFrame'),'Title').Text = nplayer.Name - - --move for bc label - nFrame.FriendLabel.Position=nFrame.FriendLabel.Position+UDim2.new(0,17,0,0) - nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,17,0,0) - - if(nFrame:FindFirstChild('FriendLabel').Image ~= '') then - nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,17,0,0) - --nFrame.FriendLabel.Position=nFrame.TitleFrame.Position+UDim2.new(nFrame.TitleFrame.Size.X.Scale,-20+nFrame.TitleFrame.Size.X.Offset,0,0) - end - - if nplayer.Name == LocalPlayer.Name then - nFrame.TitleFrame.Title.Font = 'ArialBold' - nFrame.PlayerScore.Font = 'ArialBold' - ChangeHeaderName(nplayer.Name) - local dropShadow = nFrame.TitleFrame.Title:Clone() - dropShadow.TextColor3 = Color3.new(0,0,0) - dropShadow.TextTransparency=0 - dropShadow.ZIndex=2 - dropShadow.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,1,0,1) - dropShadow.Name='DropShadow' - dropShadow.Parent= nFrame.TitleFrame - elseif LocalPlayer:IsFriendsWith(nplayer.userId) then - - end - nFrame.TitleFrame.Title.Font = 'ArialBold' - - - nFrame.Parent = ListFrame - nFrame:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0), "Out", "Quad", .5,true) - UpdateMinimize() - local nentry = {} - nentry['Frame'] = nFrame - nentry['Player'] = nplayer - nentry['ID'] = AddId - AddId = AddId + 1 - table.insert(PlayerFrames,nentry) - if #TeamFrames~=0 then - - if nplayer.Neutral then - nentry['MyTeam'] = nil - if not NeutralTeam then - AddNeutralTeam() - else - AddPlayerToTeam(NeutralTeam,nentry) - end - - else - local addedToTeam=false - for i,tval in ipairs(TeamFrames) do - if tval['MyTeam'].TeamColor == nplayer.TeamColor then - AddPlayerToTeam(tval,nentry) - nentry['MyTeam'] = tval - addedToTeam=true - end - end - if not addedToTeam then - nentry['MyTeam']=nil - if not NeutralTeam then - AddNeutralTeam() - else - AddPlayerToTeam(NeutralTeam,nentry) - end - nentry['MyTeam'] = NeutralTeam - end - end - - end - - if nplayer:FindFirstChild('leaderstats') then - LeaderstatsAdded(nentry) - end - - nplayer.ChildAdded:connect(function(nchild) - if nchild.Name == 'leaderstats' then - while AddingFrameLock do debugprint('in adding leaderstats lock') wait(1/30) end - AddingFrameLock = true - LeaderstatsAdded(nentry) - AddingFrameLock = false - end - end) - - nplayer.ChildRemoved:connect(function (nchild) - if nplayer==LocalPlayer and nchild.Name == 'leaderstats' then - LeaderstatsRemoved(nchild,nentry) - end - end) - nplayer.Changed:connect(function(prop)PlayerChanged(nentry,prop) end) - - local listener = WaitForChild(nFrame,'ClickListener') - listener.Active = true - listener.MouseButton1Down:connect(function() OnPlayerEntrySelect(nentry) end) - - AddMiddleBGFrame() - BaseUpdate() - AddingFrameLock = false -end - ---[[ - Note:major optimization can be done here - removes this player's frame if it exists, calls base update ---]] -function RemovePlayerFrame(tplayer) - while AddingFrameLock do debugprint('in removing player frame lock') wait(1/30) end - AddingFrameLock = true - - local tteam - for i,key in ipairs(PlayerFrames) do - if tplayer == key['Player'] then - if PopUpClipFrame.Parent == key['Frame'] then - PopUpClipFrame.Parent = nil - end - key['Frame']:Destroy() - tteam=key['MyTeam'] - table.remove(PlayerFrames,i) - end - end - if tteam then - for j,tentry in ipairs(tteam['MyPlayers']) do - if tentry['Player'] == tplayer then - RemovePlayerFromTeam(tteam,j) - end - end - end - - RemoveMiddleBGFrame() - UpdateMinimize() - BaseUpdate() - AddingFrameLock = false -end - -Players.ChildRemoved:connect(RemovePlayerFrame) - ----------------------------- --- Team Callback Functions ----------------------------- ---[[ - turns a list of team entries with sub lists of players into a single ordered - list, in the correct order,and of the correct length - @Args: - tframes the team entries to unroll - outframes the list to unroll these entries into ---]] -function UnrollTeams(tframes,outframes) - local numEntries = 0 - if NeutralTeam and not NeutralTeam['IsHidden'] then - for i,val in ipairs(NeutralTeam['MyPlayers']) do - numEntries = numEntries + 1 - outframes[numEntries] = val['Frame'] - end - numEntries = numEntries + 1 - outframes[numEntries] = NeutralTeam['Frame'] - end - for i,val in ipairs(tframes) do - if not val['IsHidden'] then - for j,pval in ipairs(val.MyPlayers) do - numEntries = numEntries + 1 - outframes[numEntries] = pval['Frame'] - end - numEntries = numEntries + 1 - outframes[numEntries] = val['Frame'] - end - end - -- clear any additional entries from outframes - for i = numEntries + 1,#outframes,1 do - outframes[i] = nil - end -end ---[[ - uses lua's table.sort to sort the teams ---]] -function TeamSortFunc(a,b) - if a['TeamScore'] == b['TeamScore'] then - return a['ID'] < b['ID'] - end - if not a['TeamScore'] then return false end - if not b['TeamScore'] then return true end - return a['TeamScore'] < b['TeamScore'] - -end ---[[ - consider adding lock with wait for performance - sorts each of the team's player lists induvidually, adds up the team scores. - @Args: - tentries table of team entries ---]] -function SortTeams(tentries) - - for i,val in ipairs(tentries) do - - table.sort(val['MyPlayers'],PlayerSortFunction) - AddTeamScores(val) - end - table.sort(tentries,TeamSortFunc) -end ---[[ - base update for team mode, adds up the scores of all teams, sorts them, - then unrolls them into middleframes ---]] -function TeamListModeUpdate() - RecreateScoreColumns(PlayerFrames) - SortTeams(TeamFrames) - if NeutralTeam then - AddTeamScores(NeutralTeam) - --RecreateScoreColumns(NeutralTeam['MyPlayers']) - end - UnrollTeams(TeamFrames,MiddleFrames) -end ---[[ - adds up all the score of this team's players to form the team score - @Args: - team team entry to sum the scores of ---]] -function AddTeamScores(team) - - for j = 1, #ScoreNames,1 do - local i = ScoreNames[j] - local tscore = 0 - for _,j in ipairs(team['MyPlayers']) do - local tval = j['Player']:FindFirstChild('leaderstats') and j['Player'].leaderstats:FindFirstChild(i['Name']) - if tval and not tval:IsA('StringValue') then - tscore = tscore + GetScoreValue((j['Player'].leaderstats)[i['Name'] ]) - end - end - if team['Frame']:FindFirstChild(i['Name']) then - team['Frame'][i['Name'] ].Size = UDim2.new(1 - (ScrollBarFrame.Size.X.Scale * 2),- ((j-1) * SpacingPerStat),1,0) - team['Frame'][i['Name'] ].Text = tostring(tscore) - end - end - UpdateMinimize() -end - ---[[ - finds previous team this player was on, and if it exists calls removeplayerfromteam - @Args - entry Player entry ---]] -function FindRemovePlayerFromTeam(entry) - if entry['MyTeam'] then - for j,oldEntry in ipairs(entry['MyTeam']['MyPlayers']) do - if oldEntry['Player'] == entry['Player'] then - RemovePlayerFromTeam(entry['MyTeam'],j) - return - end - end - elseif NeutralTeam then - for j,oldEntry in ipairs(NeutralTeam['MyPlayers']) do - if oldEntry['Player'] == entry['Player'] then - RemovePlayerFromTeam(NeutralTeam,j) - return - end - end - end -end ---[[ - removes a single player from a given team (not usually called directly) - @Args: - teamEntry team entry to remove player from - index index of player in 'MyPlayers' list to remove ---]] -function RemovePlayerFromTeam(teamEntry,index) - table.remove(teamEntry['MyPlayers'],index) - --if teamEntry['AutoHide'] and #teamEntry['MyPlayers'] == 0 then - if teamEntry==NeutralTeam and #teamEntry['MyPlayers']==0 then - RemoveNeutralTeam() - end -end ---[[ - adds player entry entry to teamentry - removes them from any previous team - @Args: - teamEntry entry of team to add player to - entry player entry to add to this team ---]] -function AddPlayerToTeam(teamEntry,entry) - FindRemovePlayerFromTeam(entry) - table.insert(teamEntry['MyPlayers'],entry) - entry['MyTeam'] = teamEntry - if teamEntry['IsHidden'] then - teamEntry['Frame'].Parent = ListFrame - AddMiddleBGFrame() - end - teamEntry['IsHidden'] = false -end - - -function SetPlayerToTeam(entry) - FindRemovePlayerFromTeam(entry) - -- check to see if team exists, if it does add to that team - local setToTeam = false - for i,tframe in ipairs(TeamFrames) do - -- add my entry on the new team - if tframe['MyTeam'].TeamColor == entry['Player'].TeamColor then - AddPlayerToTeam(tframe,entry) - setToTeam = true - end - end - -- if player was set to an invalid team, then set it back to neutral - if not setToTeam then - entry['MyTeam']=nil - if not NeutralTeam then - AddNeutralTeam() - else AddPlayerToTeam(NeutralTeam,entry) end - end -end - ---[[ - Note:another big one, consiter breaking up - called when any children of player changes - handles 'Neutral', teamColor, Name and MembershipType changes - @Args - entry Player entry changed - property name of property changed ---]] -function PlayerChanged(entry, property) - while PlayerChangedLock do - debugprint('in playerchanged lock') - wait(1/30) - end - PlayerChangedLock=true - if property == 'Neutral' then - -- if player changing to neutral - if entry['Player'].Neutral then - debugprint(entry['Player'].Name..'setting to neutral') - FindRemovePlayerFromTeam(entry) - entry['MyTeam']=nil - if not NeutralTeam then - debugprint(entry['Player'].Name..'creating neutral team') - AddNeutralTeam() - else - debugprint(entry['Player'].Name..'adding to neutral team') - AddPlayerToTeam(NeutralTeam,entry) - end - else -- else player switching to a team, or a weird edgecase - SetPlayerToTeam(entry) - end - BaseUpdate() - elseif property == 'TeamColor' and not entry['Player'].Neutral and entry['Player'] ~= entry['MyTeam'] then - debugprint(entry['Player'].Name..'setting to new team') - SetPlayerToTeam(entry) - BaseUpdate() - elseif property == 'Name' or property == 'MembershipType' then - entry['Frame']:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(entry['Player'].MembershipType,entry['Player'].Name) - entry['Frame'].Name = entry['Player'].Name - entry['Frame'].TitleFrame.Title.Text = entry['Player'].Name - if(entry['Frame'].BCLabel.Image ~= '') then - entry['Frame'].TitleFrame.Title.Position=UDim2.new(.01, 30, .1, 0) - end - if entry['Player'] == LocalPlayer then - entry['Frame'].TitleFrame.DropShadow.Text= entry['Player'].Name - ChangeHeaderName(entry['Player'].Name) - end - BaseUpdate() - end - PlayerChangedLock=false -end - -function OnFriendshipChanged(player,friendStatus) - for _, entry in ipairs(PlayerFrames) do - if entry['Player']==player then - local nicon = getFriendStatusIcon(friendStatus) - if nicon == '' and entry['Frame'].FriendLabel.Image ~= '' then - entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position-UDim2.new(0,17,0,0) - elseif nicon ~= '' and entry['Frame'].FriendLabel.Image == '' then - entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position+UDim2.new(0,17,0,0) - end - entry['Frame'].FriendLabel.Image = nicon +local function showBigPlayerWindow() + if container:FindFirstChild("BigPlayerlist") then + if container.BigPlayerlist.Visible then return end end -end - -LocalPlayer.FriendStatusChanged:connect(OnFriendshipChanged) - ---[[ - adds a neutral team if nessisary - Note: a lot of redundant code here, might want to refactor to share a function with insertteamframe ---]] -function AddNeutralTeam() - while NeutralTeamLock do debugprint('in neutral team 2 lock') wait() end - NeutralTeamLock = true - local defaultTeam = Instance.new('Team') - defaultTeam.TeamColor = BrickColor.new('White') - defaultTeam.Name = 'Neutral' - local nentry = {} - nentry['MyTeam'] = defaultTeam - nentry['MyPlayers'] = {} - nentry['Frame'] = MiddleTemplate:Clone() - WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = defaultTeam.Name - nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0) - nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0) - --nentry['Frame'].TitleFrame.Title.TextScaled=true - nentry['Frame'].TitleFrame.Title.Font = 'ArialBold' - nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0) - WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(StartDrag) - nentry['Frame'].ClickListener.BackgroundColor3 = Color3.new(1,1,1) - nentry['Frame'].ClickListener.BackgroundTransparency = .7 - nentry['Frame'].ClickListener.AutoButtonColor=false - nentry['AutoHide'] = true - nentry['IsHidden'] = true - for _,i in pairs(PlayerFrames) do - if i['Player'].Neutral or not i['MyTeam'] then - AddPlayerToTeam(nentry,i) - end - end - if #nentry['MyPlayers'] > 0 then - NeutralTeam = nentry - UpdateMinimize() - BaseUpdate() - end - NeutralTeamLock = false -end - -function RemoveNeutralTeam() - while NeutralTeamLock do debugprint('in neutral team lock') wait() end - NeutralTeamLock = true - NeutralTeam['Frame']:Destroy() - NeutralTeam=nil - RemoveMiddleBGFrame() - NeutralTeamLock = false -end - ---[[ - ---]] -function TeamScoreChanged(entry,nscore) - WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nscore) - entry['TeamScore'] = nscore -end ---[[ - called when child added to a team, used for autohide functionality - Note: still has teamscore, consiter removing ---]] -function TeamChildAdded(entry,nchild) - if nchild.Name == 'AutoHide' then - entry['AutoHide'] = true - elseif nchild.Name == 'TeamScore' then - WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nchild.Value) - entry['TeamScore'] = nchild.Value - nchild.Changed:connect(function() TeamScoreChanged(entry,nchild.Value) end) - end -end ---[[ - called when child added to a team, used for autohide functionality - Note: still has teamscore, consiter removing ---]] -function TeamChildRemoved(entry,nchild) - if nchild.Name == 'AutoHide' then - entry['AutoHide'] = false - elseif nchild.Name == 'TeamScore' then - WaitForChild(entry['Frame'],'PlayerScore').Text = "" - entry['TeamScore'] = nil - end -end - -function TeamChanged(entry, property) - if property=='Name' then - WaitForChild(WaitForChild(entry['Frame'],'TitleFrame'),'Title').Text = entry['MyTeam'].Name - - elseif property=='TeamColor' then - entry['Frame'].ClickListener.BackgroundColor3 = entry['MyTeam'].TeamColor.Color - - for _,i in pairs(TeamFrames) do - if i['MyTeam'].TeamColor == entry['MyTeam'] then - RemoveTeamFrame(entry['MyTeam']) --NO DUPLICATE TEAMS! + bigWindowImposter.Visible = true + bigWindowImposter:TweenSizeAndPosition(bigWindowSize, bigWindowPosition, Enum.EasingDirection.Out, bigEasingStyle, 0.3, true, + function(state) + if state == Enum.TweenStatus.Completed then + bigWindowImposter.Visible = false + if container:FindFirstChild("BigPlayerlist") then + container.BigPlayerlist.Visible = true + end end - end - - entry['MyPlayers']={} - - for _,i in pairs(PlayerFrames) do - SetPlayerToTeam(i) - end - BaseUpdate() - end + end) end ---[[ - creates team entry and frame for this team, sets up listeners for this team - adds any players intended for this team,Creates neutral team if this is the first team added - Note:might be best to break this into multiple functions to simplify - @Args: - nteam new team object added ---]] -function InsertTeamFrame(nteam) - while AddingFrameLock do debugprint('in adding team frame lock') wait(1/30) end - AddingFrameLock = true - --for _,i in pairs(TeamFrames) do - local nentry = {} - nentry['MyTeam'] = nteam - nentry['MyPlayers'] = {} - nentry['Frame'] = MiddleTemplate:Clone() - WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = nteam.Name - nentry['Frame'].TitleFrame.Title.Font = 'ArialBold' - nentry['Frame'].TitleFrame.Title.FontSize = 'Size18' - nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0) - nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0) - --nentry['Frame'].TitleFrame.Title.TextScaled=true - nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0) - WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(StartDrag) - nentry['Frame'].ClickListener.BackgroundColor3 = nteam.TeamColor.Color - nentry['Frame'].ClickListener.BackgroundTransparency = .7 - nentry['Frame'].ClickListener.AutoButtonColor=false - AddId = AddId + 1 - nentry['ID'] = AddId - nentry['AutoHide'] = false - if nteam:FindFirstChild('AutoHide') then - nentry['AutoHide'] = true - end - if nteam:FindFirstChild('TeamScore') then - TeamChildAdded(nentry,nteam.TeamScore) - +local function hideBigPlayerWindow(completed) + if playerContextMenu then + playerContextMenu.Visible = false end - nteam.ChildAdded:connect(function(nchild) TeamChildAdded(nentry,nchild) end) - nteam.ChildRemoved:connect(function(nchild) TeamChildRemoved(nentry,nchild) end) - nteam.Changed:connect(function(prop) TeamChanged(nentry,prop) end) + if container:FindFirstChild("BigPlayerlist") then + if container.BigPlayerlist.Visible == false and bigWindowImposter.Visible == false then + if completed then + completed() + end + --Already completely hidden + return + end + container.BigPlayerlist.Visible = false + end + + local completedFunction = completed + bigWindowImposter.Visible = true + bigWindowImposter:TweenSizeAndPosition(UDim2.new(0.4, 0, 0.4, 0), UDim2.new(0.3, 0, 0.3, 0), Enum.EasingDirection.In, Enum.EasingStyle.Quart, 0.15, true, + function(state) + if state == Enum.TweenStatus.Completed then + bigWindowImposter.Visible = false + if completedFunction then + completedFunction() + end + end + end) +end +local function hideSmallPlayerWindow(completed) + if playerContextMenu then + playerContextMenu.Visible = false + end + if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then + local completedFunction = completed + if topRightTrayContainer.SmallPlayerlist.Visible then + topRightTrayContainer.SmallPlayerlist:TweenPosition(UDim2.new(1,0,smallWindowPosition.Y.Scale, smallWindowPosition.Y.Offset), Enum.EasingDirection.Out, smallEasingStyle, 0.3, true, + function(state) + if state == Enum.TweenStatus.Completed then + if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then + topRightTrayContainer.SmallPlayerlist.Visible = false + end + if completedFunction then + completedFunction() + end + end + end) + return + end + end + if completed then + completed() + end +end + + +transitionWindowsFunction = function(desiredState) + if desiredState == "Big" then + minimizedState.Visible = false + hideSmallPlayerWindow() - for _,i in pairs(PlayerFrames) do - if not i['Player'].Neutral and i['Player'].TeamColor == nteam.TeamColor then - AddPlayerToTeam(nentry,i) + if previousBigPlayerList ~= nil then + if previousBigPlayerList ~= container:FindFirstChild("BigPlayerlist") then + pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) + previousBigPlayerList = nil + previousBigPlayerList = container:FindFirstChild("BigPlayerlist") + end + else + previousBigPlayerList = container:FindFirstChild("BigPlayerlist") end - end - nentry['IsHidden'] = false - if not nentry['AutoHide'] or #nentry['MyPlayers'] > 0 then - - nentry['Frame'].Parent = ListFrame - nentry['Frame']:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0), "Out", "Quad", .5,true) - AddMiddleBGFrame() - else - nentry['IsHidden'] = true - nentry['Frame'].Parent = nil - end - table.insert(TeamFrames,nentry) - UpdateMinimize() - BaseUpdate() - if #TeamFrames == 1 and not NeutralTeam then - AddNeutralTeam() - end - AddingFrameLock = false -end ---[[ - removes team from team list - @Args: - nteam Teamobject to remove ---]] -function RemoveTeamFrame(nteam) - while AddingFrameLock do debugprint('in removing team frame lock') wait(1/30) end - AddingFrameLock = true - if IsMinimized.Value then - -- ListFrame.Position = ListFrame.Position + UDim2.new(0,0,MiddleTemplate.Size.Y.Scale,0) - end - local myEntry - for i,key in ipairs(TeamFrames) do - if nteam == key['MyTeam'] then - myEntry = key - key['Frame']:Destroy() - table.remove(TeamFrames,i) - end - end - if #TeamFrames==0 then - if NeutralTeam then - RemoveNeutralTeam() - end - end - for i,key in ipairs(myEntry['MyPlayers']) do - RemovePlayerFromTeam(myEntry,i) - PlayerChanged(key, 'TeamColor') - end - RemoveMiddleBGFrame() - BaseUpdate() - AddingFrameLock = false -end - -function TeamAdded(nteam) - InsertTeamFrame(nteam) -end - -function TeamRemoved(nteam) - RemoveTeamFrame(nteam) -end - --------------------------------- ---[[ - called when ANYTHING changes the state of the playerlist - re-sorts everything,assures correct positions of all elements ---]] -function BaseUpdate() - while BaseUpdateLock do debugprint('in baseupdate lock') wait(1/30) end - BaseUpdateLock = true - --print ('baseupdate') - UpdateStatNames() - - if #TeamFrames == 0 then - PlayerListModeUpdate() - else - TeamListModeUpdate() - end - for i,key in ipairs(MiddleFrames) do - if key.Parent ~= nil then - key:TweenPosition(UDim2.new(.5,0,((#MiddleFrames - (i)) * key.Size.Y.Scale),0), "Out", "Quad", .9,true) - end - end - if not IsMinimized.Value and #MiddleFrames>DefaultEntriesOnScreen then - UpdateScrollPosition() - end - - UpdateMinimize() - - UpdateScrollBarSize() - UpdateScrollPosition() - - UpdateScrollBarVisibility() - --debugprint('EndBaseUpdate') - BaseUpdateLock = false -end - ---[[ - code for attaching tab key to maximizing player list ---]] -game.GuiService:AddKey("\t") -local LastTabTime = time() -game.GuiService.KeyPressed:connect( -function(key) - if key == "\t" then - debugprint('caught tab key') - local modalCheck, isModal = pcall(function() return game.GuiService.IsModalDialog end) - if modalCheck == false or (modalCheck and isModal == false) then - if time() - LastTabTime > 0.4 then - LastTabTime = time() - if IsTabified.Value then - if not IsMaximized.Value then - ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Quad',1,true) - IsMaximized.Value = true + 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 - ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Quad',1,true) - IsMaximized.Value = false - IsMinimized.Value=true + previousBigPlayerList.Visible = true end - else - ToggleMaximize() + end) + end) + if centerDialogSupported == false then + print("Exception", msg) + showBigPlayerWindow() + end + else + showBigPlayerWindow() + end + currentWindowState = "Big" + elseif desiredState == "Small" then + minimizedState.Visible = false + if previousBigPlayerList ~= nil then + pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) + previousBigPlayerList = nil + end + + hideBigPlayerWindow() + if topRightTrayContainer:FindFirstChild("SmallPlayerlist") then + if not topRightTrayContainer.SmallPlayerlist.Visible or topRightTrayContainer.SmallPlayerlist.Position ~= smallWindowPosition then + topRightTrayContainer.SmallPlayerlist.Visible = true + topRightTrayContainer.SmallPlayerlist:TweenPosition(smallWindowPosition, Enum.EasingDirection.Out, smallEasingStyle, 0.3, true) + end + end + currentWindowState = "Small" + elseif desiredState == "None" then + if previousBigPlayerList ~= nil then + pcall(function() game.GuiService:RemoveCenterDialog(previousBigPlayerList) end) + previousBigPlayerList = nil + end + + local smallDone = false + local bigDone = false + hideSmallPlayerWindow( + function() + smallDone = true + if bigDone and smallDone then + minimizedState.Visible = true end - + end) + hideBigPlayerWindow( + function() + bigDone = true + if bigDone and smallDone then + minimizedState.Visible = true + end + end) + currentWindowState = "None" + end +end + +local function getStatValuesForPlayer(player) + local leaderstats = player:FindFirstChild("leaderstats") + if leaderstats then + local children = leaderstats:GetChildren() + if children then + local result = {} + --Just go based on position + for i, stat in ipairs(children) do + if stat:IsA("IntValue") then + table.insert(result, stat) + else + table.insert(result, 0) + end + end + + return result, leaderstats + end + end + return nil +end + +--ChildAdded on Player (if it's name is "leaderstats") + +if UserSettings and LoadLibrary then + + RbxGui,msg = LoadLibrary("RbxGui") + + local function createTeamName(name, color) + local fontHeight = 20 + local frame = Instance.new("Frame") + frame.Name = "Team-" .. name + frame.BorderSizePixel = 0 + frame.BackgroundTransparency = 0.5 + frame.BackgroundColor3 = Color3.new(1,1,1) + frame.Size = UDim2.new(1, 0, 0, fontHeight) + frame.Position = UDim2.new(0,0,0,0) + + local label = Instance.new("TextLabel") + label.Name = "NameLabel" + label.Text = " " .. name + label.Font = Enum.Font.ArialBold + label.FontSize = Enum.FontSize.Size18 + label.Position = UDim2.new(0,0,0,0) + label.Size = UDim2.new(1,0,1,0) + label.TextColor3 = Color3.new(1,1,1) + label.BackgroundTransparency = 0.5 + label.BackgroundColor3 = getColor(color) + label.BorderSizePixel = 0 + label.TextXAlignment = Enum.TextXAlignment.Left + 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 "rbxasset://textures/ui/PlayerlistFriendIcon.png" + elseif friendStatus == Enum.FriendStatus.FriendRequestSent then + return "rbxasset://textures/ui/PlayerlistFriendRequestSentIcon.png" + elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then + return "rbxasset://textures/ui/PlayerlistFriendRequestReceivedIcon.png" + else + error("Unknown FriendStatus: " .. friendStatus) + end + end + + local function getMembershipTypeIcon(membershipType) + if membershipType == Enum.MembershipType.None then + return "" + elseif membershipType == Enum.MembershipType.BuildersClub then + return "rbxasset://textures/ui/TinyBcIcon.png" + elseif membershipType == Enum.MembershipType.TurboBuildersClub then + return "rbxasset://textures/ui/TinyTbcIcon.png" + elseif membershipType == Enum.MembershipType.OutrageousBuildersClub then + return "rbxasset://textures/ui/TinyObcIcon.png" + else + error("Uknown membershipType" .. membershipType) + end + end + + + local function updatePlayerFriendStatus(nameObject, friendStatus) + local fontHeight = 20 + + local friendIconImage = getFriendStatusIcon(friendStatus) + nameObject.MembershipTypeLabel.FriendStatusLabel.Visible = (friendIconImage ~= nil) + + if friendIconImage ~= nil then + --Show friend icon + nameObject.MembershipTypeLabel.FriendStatusLabel.Image = friendIconImage + nameObject.NameLabel.Position =UDim2.new(0,2*fontHeight,0,1) + nameObject.NameLabel.Size = UDim2.new(1,-2*fontHeight,1,-2) + else + --Hide the friend icon + nameObject.NameLabel.Position = UDim2.new(0,fontHeight+1,0,1) + nameObject.NameLabel.Size = UDim2.new(1,-(fontHeight+1),1,-2) + end + end + local function updatePlayerName(nameObject, membershipStatus, teamColor) + local fontHeight = 20 + + 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("Frame") + frame.Name = "Player_" .. 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("ImageLabel") + membershipStatusLabel.Name = "MembershipTypeLabel" + 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("ImageLabel") + friendStatusLabel.Name = "FriendStatusLabel" + friendStatusLabel.Visible = false + friendStatusLabel.BackgroundTransparency = 1 + friendStatusLabel.Size = UDim2.new(1,0,1,0) + friendStatusLabel.Position = UDim2.new(1,0,0,0) + friendStatusLabel.Parent = membershipStatusLabel + + local changeNameFunction + local nameLabel = Instance.new("TextLabel") + nameLabel.Name = "NameLabel" + nameLabel.Text = name + nameLabel.Font = Enum.Font.ArialBold + nameLabel.FontSize = Enum.FontSize.Size14 + nameLabel.TextColor3 = Color3.new(1,1,1) + nameLabel.BackgroundTransparency = 1 + nameLabel.BackgroundColor3 = Color3.new(0,0,0) + nameLabel.TextXAlignment = Enum.TextXAlignment.Left + nameLabel, changeNameFunction = RbxGui.AutoTruncateTextObject(nameLabel) + nameLabel.Parent = frame + + updatePlayerName(frame, membershipStatus, teamColor) + if supportFriends 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("TextLabel") + textLabel.Name = "Stat" .. 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 = "" + 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("Frame") + frame.Name = "Headers" + frame.BorderSizePixel = 0 + frame.BackgroundColor3 = Color3.new(0,0,0) + frame.BackgroundTransparency = 1 + + local nameSize + if isBig then + nameSize = 0.5 + elseif numColumns == 1 then + nameSize = 0.7 + elseif numColumns == 2 then + nameSize = 0.6 + else + nameSize = 0.45 + end + frame.Size = UDim2.new(1-nameSize, 0, 1,0) + if isBig then + frame.Position = UDim2.new(nameSize,-25, 0,0) + else + frame.Position = UDim2.new(nameSize,0, 0,0) + end + + local i = 1 + while i <= numColumns do + local headerColumn, changeText = createStatColumn(i, numColumns, false, nil, true) + 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("Frame") + frame.Name = nameObject.Name .. "_WithStats" + frame.BorderSizePixel = 0 + frame.BackgroundColor3 = nameObject.BackgroundColor3 + frame.BackgroundTransparency = nameObject.BackgroundTransparency + frame.Size = nameObject.Size + frame.Position = nameObject.Position + + nameObject.BackgroundTransparency = 1 + + if numColumns == 0 then + nameObject.Size = UDim2.new(1,0,1,0) + nameObject.Position = UDim2.new(0,0,0,0) + nameObject.Parent = frame + return frame + end + + local statFrame = Instance.new("Frame") + statFrame.Name = "Stats" + if isTeam then + statFrame.BorderSizePixel = 0 + statFrame.BackgroundColor3 = nameObject.NameLabel.BackgroundColor3 + statFrame.BackgroundTransparency = nameObject.NameLabel.BackgroundTransparency + else + statFrame.BackgroundTransparency = 1 + end + + local nameSize + if isBig then + nameSize = 0.5 + elseif numColumns == 1 then + nameSize = 0.7 + elseif numColumns == 2 then + nameSize = 0.6 + else + nameSize = 0.45 + end + nameObject.Size = UDim2.new(nameSize, 0, 1, 0) + nameObject.Position = UDim2.new(0, 0, 0, 0) + statFrame.Size = UDim2.new(1-nameSize,0, 1,0) + statFrame.Position = UDim2.new(nameSize,0, 0,0) + + nameObject.Parent = frame + statFrame.Parent = frame + + local textChangers = {} + local i = 1 + while i <= numColumns do + local statColumn, changeText = createStatColumn(i, numColumns, isTeam, statFrame.BackgroundColor3) + statColumn.Parent = statFrame + table.insert(textChangers, changeText) + + i = i + 1 + end + + return frame, statFrame, textChangers + end + + local function createAlternatingRows(objects) + for i, line in ipairs(objects) do + if i % 2 == 0 then + line.BackgroundTransparency = 1 + else + line.BackgroundTransparency = 0.95 end end end -end) + local removeFromTeam = nil - ---------------------------- - -- Hookups and initialization - ---------------------------- -function debugPlayerAdd(p) - InsertPlayerFrame(p) -end - -while not game:GetService('Teams') do wait(1/30) debugprint('Waiting For Teams') end -for _,i in pairs(game.Teams:GetTeams()) do TeamAdded(i) end -for _,i in pairs(Players:GetPlayers()) do Spawn(function() debugPlayerAdd(i) end) end--InsertPlayerFrame(i) end - -game.Teams.ChildAdded:connect(TeamAdded) -game.Teams.ChildRemoved:connect(TeamRemoved) -Players.ChildAdded:connect(function(tplayer) Spawn(function() debugPlayerAdd(tplayer) end) end)--InsertPlayerFrame) - -InitReportAbuse() -AreNamesExpanded.Value = true -BaseUpdate() - - - ---UGGGLY,find a better way later -wait(2) -IsPersonalServer= not not game.Workspace:FindFirstChild("PSVariable") - - ---------------------------- - -- Running Logic - ---------------------------- - - --debug stuffs, will only run for 'newplayerlistisbad' - ---REMOVEME - - - if LocalPlayer.Name == 'newplayerlistisbad' or LocalPlayer.Name == 'Imtotallyadmin' then - debugFrame.Parent = ScreenGui - Spawn(function() - while true do - local str_players='' - for _,i in pairs(game.Players:GetPlayers()) do - str_players= str_players .." " .. i.Name - end - debugplayers.Text=str_players - wait(.5) + local function clearTableEntry(obj, tableInfo) + if tableInfo.MainObjectSmall then + tableInfo.MainObjectSmall.Parent = nil + tableInfo.MainObjectSmall = nil end - end) - end - ---[[ -function EnsureValidity() - while true do - --make sure all players are in the player list - --and make sure there are no entries that corespond to non-existant players - local unfoundEntries={} - for k,v in pairs(PlayerFrames) do - unfoundEntries[k] = v + if tableInfo.MainObjectBig then + tableInfo.MainObjectBig.Parent = nil + tableInfo.MainObjectBig = nil end - --for all players - for _,i in pairs(Players:GetPlayers()) do - local foundPlayer=false - --for all known players - for entryIndex,j in pairs(PlayerFrames) do - -- if I know about this player, tag it - if i==j['Player'] then - foundPlayer=true - unfoundEntries[entryIndex]=nil - end + if tableInfo.Connections then + for i, connection in ipairs(tableInfo.Connections) do + connection:disconnect() end - --if this player is not known - if not foundPlayer then - wait(.5) - --do a double check - for _,j in pairs(PlayerFrames) do - if i==j['Player'] then - foundPlayer=true + tableInfo.Connections = nil + end + if tableInfo.LeaderStatConnections then + for i, connection in ipairs(tableInfo.LeaderStatConnections) do + connection:disconnect() + end + tableInfo.LeaderStatConnections = nil + end + if tableInfo.CurrentTeam then + removeFromTeam(obj) + tableInfo.CurrentTeam = nil + end + if tableInfo.Players then + for i, player in ipairs(tableInfo.Players) do + playerTable[player].CurrentTeam = nil + end + tableInfo.Players = {} + end + if tableInfo.StatValues then + tableInfo.StatValues = nil + end + end + + local function resetPlayerTable() + for player, info in pairs(playerTable) do + clearTableEntry(player, info) + playerTable[player] = nil + end + playerTable = {} + end + + local function resetTeamTable() + for team, info in pairs(teamTable) do + clearTableEntry(team, info) + teamTable[team] = nil + end + teamTable = {} + teamColorTable = {} + end + + local function getBoardTypeInfo() + local isTeam = (currentBoardType == "TeamScore" or currentBoardType == "TeamList") + local isScore = (currentBoardType == "TeamScore" or currentBoardType == "PlayerScore") + return isTeam, isScore + end + + + local function recomputeTeamScore(team, column) + if not team or team == "Neutral" then + return + end + + local function recomputeScoreHelper(statChangers) + if statChangers and column <= #statChangers then + local sum = 0 + for i, p in ipairs(teamTable[team].Players) do + if playerTable[p].StatValues and column <= #playerTable[p].StatValues then + sum = sum + playerTable[p].StatValues[column].Value end end - if not foundPlayer then - InsertPlayerFrame(i) - debugOutput.Text= "Manual Insertion! " .. i.Name + statChangers[column](sum) + end + end + + recomputeScoreHelper(teamTable[team].StatChangersSmall) + recomputeScoreHelper(teamTable[team].StatChangersBig) + end + local function recomputeCompleteTeamScore(team) + local col = 1 + while col <= currentStatCount do + recomputeTeamScore(team, col) + col = col + 1 + end + end + removeFromTeam = function(player) + if playerTable[player].CurrentTeam ~= nil and teamTable[playerTable[player].CurrentTeam] ~= nil then + ArrayRemove(teamTable[playerTable[player].CurrentTeam].Players, player) + recomputeCompleteTeamScore(playerTable[player].CurrentTeam) + playerTable[player].CurrentTeam = nil + end + end + + local function assignToTeam(player) + local isTeam, isScore = getBoardTypeInfo() + + if isTeam then + local newTeam = nil + + if player.Neutral or teamColorTable[player.TeamColor.Name] == nil then + newTeam = "Neutral" + else + newTeam = teamColorTable[player.TeamColor.Name] + end + + if playerTable[player].CurrentTeam == newTeam then + return + end + + removeFromTeam(player) + + playerTable[player].CurrentTeam = newTeam + if teamTable[newTeam] then table.insert(teamTable[newTeam].Players, player) end + + if newTeam == "Neutral" 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]["NameObject" .. suffix] = teamObject + if isScore then + local statObject + local textChangers + teamObject, statObject, textChangers = createStatColumns(teamObject, numStatColumns, true, suffix == "Big") + teamTable[team]["StatObject" .. suffix] = statObject + teamTable[team]["StatChangers" .. suffix] = textChangers + end + teamTable[team]["MainObject" .. suffix] = teamObject + 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("Frame") + playerContextMenu.Name = "PlayerListContextMenu" + playerContextMenu.BackgroundTransparency = 1 + playerContextMenu.Visible = false + + local playerContextMenuButton = Instance.new("TextButton") + playerContextMenuButton.Name = "PlayerListContextMenuButton" + playerContextMenuButton.Text = "" + 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 == "Button" then + local button = Instance.new("TextButton") + button.Name = "ContextButton" .. i + button.BackgroundColor3 = Color3.new(0,0,0) + button.BorderSizePixel = 0 + button.TextXAlignment = Enum.TextXAlignment.Left + button.Text = " " .. contextElement.Text + button.Font = Enum.Font.Arial + button.FontSize = Enum.FontSize.Size14 + button.Size = UDim2.new(1, 8, 0, elementHeight) + button.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 == "Label" then + local frame = Instance.new("Frame") + frame.Name = "ContextLabel" .. i + frame.BackgroundTransparency = 1 + frame.Size = UDim2.new(1, 8, 0, elementHeight) + + local label = Instance.new("TextLabel") + label.Name = "Text1" + label.BackgroundTransparency = 1 + label.BackgroundColor3 = Color3.new(1,1,1) + label.BorderSizePixel = 0 + label.TextXAlignment = Enum.TextXAlignment.Left + label.Font = Enum.Font.ArialBold + label.FontSize = Enum.FontSize.Size14 + label.Position = UDim2.new(0.0, 0, 0, 0) + label.Size = UDim2.new(0.5, 0, 1, 0) + label.TextColor3 = Color3.new(1,1,1) + label.ZIndex = 4 + label.Parent = frame + element.Label1 = label + + if element.GetText2 then + label = Instance.new("TextLabel") + label.Name = "Text2" + label.BackgroundTransparency = 1 + label.BackgroundColor3 = Color3.new(1,1,1) + label.BorderSizePixel = 0 + label.TextXAlignment = Enum.TextXAlignment.Right + label.Font = Enum.Font.Arial + label.FontSize = Enum.FontSize.Size14 + label.Position = UDim2.new(0.5, 0, 0, 0) + label.Size = UDim2.new(0.5, 0, 1, 0) + label.TextColor3 = Color3.new(1,1,1) + label.ZIndex = 4 + label.Parent = frame + element.Label2 = label + end + frame.Parent = playerContextMenuButton + element.Label = frame + element.Element = frame + end + end + + playerContextMenu.ZIndex = 4 + playerContextMenu.MouseLeave:connect(function() playerContextMenu.Visible = false end) + robloxLock(playerContextMenu) + playerContextMenu.Parent = script.Parent + + 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("Error in IsVisible call: " .. visible) + end + end + + if contextElement.Type == "Button" 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("Error in IsActive call: " .. 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 == "Label" 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 = " " .. text + else + print("Error in GetText1 call: " .. text) + end + + if contextElement.GetText2 then + local success, text = pcall(function() return contextElement.GetText2(currentContextMenuPlayer) end) + if success then + contextElement.Label2.Text = " " .. text + else + print("Error in GetText2 call: " .. 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 >= script.Parent.AbsoluteSize.X then + x = script.Parent.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) + if not player then return nil end + + local isTeam, isScore = getBoardTypeInfo() + + local playerObject = nil + local changePlayerNameFunction = nil + local currentColor = nil + if isTeam and not player.Neutral then + currentColor = player.TeamColor.Color + else + currentColor = Color3.new(1,1,1) + end + playerObject, changePlayerNameFunction = createPlayerName(player.Name, player.MembershipType, currentColor, getFriendStatus(player)) + + if not playerTable[player] then + playerTable[player] = {} + end + if not playerTable[player].Connections then + playerTable[player].Connections = {} + end + if not playerTable[player].CurrentTeam then + playerTable[player].CurrentTeam = nil + end + playerTable[player]["NameObject" .. suffix] = playerObject + playerTable[player]["ChangeName" .. suffix] = changePlayerNameFunction + + if isScore then + local statObject = nil + local textChangers = nil + playerObject, statObject, textChangers = createStatColumns(playerObject, numStatColumns, false, suffix == "Big") + playerTable[player]["StatObject" .. suffix]= statObject + playerTable[player]["StatChangers" .. suffix] = textChangers + + local statValues, leaderstats = getStatValuesForPlayer(player) + if not statValues or #statValues < numStatColumns then + if not playerTable[player].LeaderStatConnections then + playerTable[player].LeaderStatConnections = {} + end + --Setup a listener to see when this data gets filled in + if not leaderstats then + --We don't even have a leaderstats child, wait for one + table.insert(playerTable[player].LeaderStatConnections, + player.ChildAdded:connect( + function(child) + if child.Name == "leaderstats" then + --Connections will be torn down + recreatePlayerFunction(player) + else + table.insert(playerTable[player].LeaderStatConnections, + child.Changed:connect( + function(prop) + if prop == "Name" and child.Name == "leaderstats" then + --Connections will be torn down + recreatePlayerFunction(player) + end + end)) + end + end)) + else + --We have a leaderstats, but not enough children, recreate if we get them + table.insert(playerTable[player].LeaderStatConnections, + leaderstats.ChildAdded:connect( + function(child) + --TODO only look for IntValue + recreatePlayerFunction(player) + end) + ) + table.insert(playerTable[player].LeaderStatConnections, + leaderstats.AncestryChanged:connect( + function(child) + --We got deleted, try again + recreatePlayerFunction(player) + end) + ) + end + end + if statValues then + if not playerTable[player].StatValues then + playerTable[player].StatValues = {} + end + local pos = 1 + while pos <= numStatColumns and pos <= #statValues do + local currentColumn = pos + local statValue = statValues[pos] + local statChanger = textChangers[pos] + + local updateStat = function(val) + statChanger(val) + if playerTable[player] ~= nil then recomputeTeamScore(playerTable[player].CurrentTeam, currentColumn) end + end + if pos > #playerTable[player].StatValues then + table.insert(playerTable[player].StatValues, statValue) + end + + if type(statValue) ~= "number" and statValue["Changed"] then + table.insert(playerTable[player].Connections, + statValue.Changed:connect(updateStat) + ) + end + + table.insert(playerTable[player].Connections, + statValue.AncestryChanged:connect( + function() + recreatePlayerFunction(player) + end) + ) + updateStat(statValue.Value) + pos = pos + 1 + end + end + end + + if supportFriends and player ~= game.Players.LocalPlayer and player.userId > 0 and game.Players.LocalPlayer.userId > 0 then + local button = Instance.new("TextButton") + button.Name = playerObject.Name .. "Button" + button.Text = "" + button.Active = false + button.Size = playerObject.Size + button.Position = playerObject.Position + button.BackgroundColor3 = playerObject.BackgroundColor3 + + local secondButton = Instance.new("TextButton") + secondButton.Name = playerObject.Name .. "RealButton" + secondButton.Text = "" + secondButton.BackgroundTransparency = 1 + secondButton.BackgroundColor3 = playerObject.BackgroundColor3 + local theNameLabel = playerObject:findFirstChild("NameLabel",true) + if theNameLabel then + theNameLabel.TextColor3 = Color3.new(0,0,0) + secondButton.Parent = theNameLabel.FullNameLabel + end + secondButton.Parent.BackgroundTransparency = 1 + secondButton.Parent.Visible = true + secondButton.ZIndex = 2 + secondButton.Size = UDim2.new(1,0,1,0) + + local previousTransparency = nil + table.insert(playerTable[player].Connections, + secondButton.MouseEnter:connect( + function() + if previousTransparency == nil then + previousTransparency = secondButton.BackgroundTransparency + end + + if lightBackground then + secondButton.Parent.BackgroundTransparency = 0 + else + secondButton.Parent.BackgroundTransparency = 1 + end + end)) + table.insert(playerTable[player].Connections, + secondButton.MouseLeave:connect( + function() + if previousTransparency ~= nil then + 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]["MainObject" .. suffix] = button + + playerObject = button + else + playerTable[player]["MainObject" .. suffix] = playerObject + + if player == game.Players.LocalPlayer and supportFriends then + table.insert(playerTable[player].Connections, + player.FriendStatusChanged:connect( + function(otherPlayer, friendStatus) + if playerTable[otherPlayer] then + updatePlayerFriendStatus(playerTable[otherPlayer]["NameObject" .. suffix], friendStatus) + end + end) + ) + end + end + table.insert(playerTable[player].Connections, + player.Changed:connect( + function(prop) + if prop == "MembershipType" then + updatePlayerName(playerTable[player]["NameObject" .. suffix], player.MembershipType, currentColor) + elseif prop == "Name" then + playerTable[player]["ChangeName" .. suffix](player.Name) + elseif prop == "Neutral" or prop == "TeamColor" then + assignToTeam(player) + end + end) + ) + return playerObject + end + + local function 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 + if teamTable[team][objectName] then order[teamTable[team][objectName]] = pos end + pos = pos + 1 + for i, player in ipairs(teamTable[team].Players) do + if playerTable[player] then + if playerTable[player][objectName] ~= nil then order[playerTable[player][objectName]] = pos end + pos = pos + 1 + end end end + if #teamTable["Neutral"].Players > 0 then + teamTable["Neutral"][objectName].Parent = scrollFrame + order[teamTable["Neutral"][objectName]] = pos + pos = pos + 1 + for i, player in ipairs(teamTable["Neutral"].Players) do + if playerTable[player][objectName] ~= nil then order[playerTable[player][objectName]] = pos end + pos = pos + 1 + end + else + teamTable["Neutral"][objectName].Parent = nil + end + else + local players = getPlayers() + for i, player in ipairs(players) do + if playerTable[player] and playerTable[player][objectName] ~= nil then order[playerTable[player][objectName]] = pos end + pos = pos + 1 + end end - --for any additional entries, never found, remove them - for _,j in pairs(unfoundEntries) do - RemovePlayerFrame(j['Player']) - debugOutput.Text= "Player Manual Removal! " ..j['Player'].Name + + table.sort(scrollOrder, + function(a,b) + return order[a] < order[b] + end) + end + + local function createPlayerListBasics(frame, isBig) + local headerFrame = Instance.new("Frame") + headerFrame.Name = "Header" + headerFrame.BackgroundTransparency = 1 + headerFrame.Size = UDim2.new(1,-13,0,26) + headerFrame.Position = UDim2.new(0,0,0,0) + headerFrame.Parent = frame + + local lowerPaneFrame = Instance.new("Frame") + lowerPaneFrame.Name = "ScrollingArea" + lowerPaneFrame.BackgroundTransparency = 1 + lowerPaneFrame.Size = UDim2.new(1,-3,1,-26) + if not isBig then lowerPaneFrame.Size = UDim2.new(1,-3,1,-30) end + lowerPaneFrame.Position = UDim2.new(0,0,0,26) + lowerPaneFrame.Parent = frame + + local scrollOrder = {} + local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(scrollOrder) + + local scrollBar = Instance.new("Frame") + scrollBar.Name = "ScrollBar" + scrollBar.BackgroundTransparency = 0.9 + scrollBar.BackgroundColor3 = Color3.new(1,1,1) + scrollBar.BorderSizePixel = 0 + scrollBar.Size = UDim2.new(0, 17, 1, -36) + if isBig then scrollBar.Size = UDim2.new(0, 17, 1, -61) end + scrollBar.Parent = lowerPaneFrame + + scrollFrame.Parent = lowerPaneFrame + scrollUp.Parent = lowerPaneFrame + scrollDown.Parent = lowerPaneFrame + + if isBig then + scrollFrame.Position = UDim2.new(0,0,0,0) + scrollUp.Position = UDim2.new(1,-41,0,5) + scrollDown.Position = UDim2.new(1,-41,1,-35) + scrollBar.Position = UDim2.new(1, -41, 0, 24) + + scrollFrame.Size = UDim2.new(1,-48,1,-16) + headerFrame.Size = UDim2.new(1,-20,0,32) + + else + scrollBar.Position = UDim2.new(1, -15, 0, 14) + scrollBar.Size = UDim2.new(0,17,1,-36) + scrollFrame.Position = UDim2.new(0,1,0,0) + scrollUp.Position = UDim2.new(1,-15,0,-5) + scrollDown.Position = UDim2.new(1,-15,1,-20) + + lowerPaneFrame.Position = UDim2.new(0,0,0,30) + + local toggleScrollBar = function(visible) + if visible then + scrollFrame.Size = UDim2.new(1,-16,1,0) + headerFrame.Size = UDim2.new(1,-16,0,smallWindowHeaderYSize) + else + scrollFrame.Size = UDim2.new(1,0,1,0) + headerFrame.Size = UDim2.new(1,5,0,smallWindowHeaderYSize) + end + scrollUp.Visible = visible + scrollDown.Visible = visible + scrollBar.Visible = visible + end + scrollUp.Changed:connect(function(prop) + if prop == "Active" then + toggleScrollBar(scrollUp.Active or scrollDown.Active) + end + end) + + scrollDown.Changed:connect(function(prop) + if prop == "Active" then + toggleScrollBar(scrollUp.Active or scrollDown.Active) + end + end) + + toggleScrollBar(scrollUp.Active or scrollDown.Active) end - wait(1/30) - --make sure there are no gaps or overlaps in the playerlist - while GetEntryListLength()>#MiddleFrameBackgrounds do - AddMiddleBGFrame() + return headerFrame, scrollFrame, recalculateScroll, scrollOrder + end + + createBoardsFunction = function (boardType, numStatColumns) + local smallFrame = Instance.new("Frame") + smallFrame.Name = "SmallPlayerlist" + smallFrame.Position = smallWindowPosition + smallFrame.Active = false + smallFrame.Size = smallWindowSize + smallFrame.BackgroundColor3 = Color3.new(0,0,0) + smallFrame.BackgroundTransparency = 0.7 + smallFrame.BorderSizePixel = 0 + + local bigFrame = Instance.new("Frame") + bigFrame.Name = "BigPlayerlist" + bigFrame.Size = bigWindowSize + bigFrame.Position = bigWindowPosition + bigFrame.BackgroundColor3 = Color3.new(0,0,0) + bigFrame.BackgroundTransparency = 0.7 + bigFrame.BorderSizePixel = 0 + bigFrame.Visible = false + + local bigFrameWrapper = Instance.new("Frame") + bigFrameWrapper.Name = "Expander" + bigFrameWrapper.Size = UDim2.new(1,21,1,16) + bigFrameWrapper.Position = UDim2.new(0, 0, 0,0) + bigFrameWrapper.BackgroundTransparency = 1 + bigFrameWrapper.Parent = bigFrame + + local smallHeaderFrame, scrollFrameSmall, recalculateScrollSmall, scrollOrderSmall = createPlayerListBasics(smallFrame, false) + local bigHeaderFrame, scrollFrameBig, recalculateScrollBig, scrollOrderBig = createPlayerListBasics(bigFrameWrapper, true) + + local playerListButton = Instance.new("ImageButton") + playerListButton.Name = "GoBigButton" + playerListButton.BackgroundTransparency = 1 + playerListButton.Image = "rbxasset://textures/ui/playerlist_small_maximize.png" + playerListButton.Size = UDim2.new(0.0, 35, 0, 29) + playerListButton.Position = UDim2.new(0, 0, 0, 0) + playerListButton.MouseButton1Click:connect( + function() + toggleBigWindow() + end) + playerListButton.Parent = smallHeaderFrame + + playerListButton = Instance.new("ImageButton") + playerListButton.Name = "CloseButton" + playerListButton.BackgroundTransparency = 1 + playerListButton.Image = "rbxasset://textures/ui/playerlist_small_hide.png" + playerListButton.Size = UDim2.new(0.0, 38, 0, 29) + playerListButton.Position = UDim2.new(0, 35, 0, 0) + playerListButton.MouseButton1Click:connect( + function() + transitionWindowsFunction("None") + end) + playerListButton.Parent = smallHeaderFrame + + playerListButton = Instance.new("ImageButton") + playerListButton.Name = "CloseButton" + playerListButton.Image = "rbxasset://textures/ui/playerlist_big_hide.png" + playerListButton.BackgroundTransparency = 1 + playerListButton.Size = UDim2.new(0.0, 29, 0, 29) + playerListButton.Position = UDim2.new(1, -30, 0.5, -15) + playerListButton.MouseButton1Click:connect( + function() + toggleBigWindow() + end) + playerListButton.Parent = bigHeaderFrame + + local placeName = Instance.new("TextLabel") + placeName.Name = "PlaceName" + placeName.Text = " Player List" + 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 > 3 then + numStatColumns = 3 + end + createStatHeaders(statColumns, numStatColumns, false).Parent = smallHeaderFrame + createStatHeaders(statColumns, currentStatCount, true).Parent = bigHeaderFrame end - while GetEntryListLength()<#MiddleFrameBackgrounds do - RemoveMiddleBGFrame() + + --Clean up all old stuff + resetPlayerTable() + + for i, player in ipairs(players) do + local playerObject = buildPlayerObject(player, numStatColumns, "Small") + table.insert(scrollOrderSmall, playerObject) + playerObject.Parent = scrollFrameSmall + + playerObject = buildPlayerObject(player, currentStatCount, "Big") + table.insert(scrollOrderBig, playerObject) + playerObject.Parent = scrollFrameBig end - wait(1/30) - --remove neutral team if it shouldn't exist - if NeutralTeam and (#NeutralTeam['MyPlayers']==0 or #TeamFrames==0) then - wait(.5) - if NeutralTeam and (#NeutralTeam['MyPlayers']==0 or #TeamFrames==0) then - RemoveNeutralTeam() - debugOutput.Text= "Manual removal of neutral team! " + + --Clean up old stuff + resetTeamTable() + + local teamStatObjects = {} + if isTeam then + local teams = getTeams() + local i = #teams + while i >= 1 do + --We go backwards so the "first" team color gets the team + local team = teams[i] + teamColorTable[team.TeamColor.Name] = team + i = i - 1 + end + + --Adding/Removing a Team causes a full invalidation of the board + for i, team in ipairs(teams) do + local teamObject = buildTeamObject(team, numStatColumns, "Small") + table.insert(scrollOrderSmall, teamObject) + teamObject.Parent = scrollFrameSmall + + teamObject = buildTeamObject(team, currentStatCount, "Big") + table.insert(scrollOrderBig, teamObject) + teamObject.Parent = scrollFrameBig + end + + teamTable["Neutral"] = {} + teamTable["Neutral"].Players = {} + + local neutralTeamObject = createTeamName("Neutral", BrickColor.palette(8)) + teamTable["Neutral"].NameObjectSmall = neutralTeamObject + teamTable["Neutral"].StatObjectSmall = nil + teamTable["Neutral"].MainObjectSmall = neutralTeamObject + table.insert(scrollOrderSmall, neutralTeamObject) + + neutralTeamObject = createTeamName("Neutral", BrickColor.palette(8)) + teamTable["Neutral"].NameObjectBig = neutralTeamObject + teamTable["Neutral"].StatObjectBig = nil + teamTable["Neutral"].MainObjectBig = neutralTeamObject + table.insert(scrollOrderBig, neutralTeamObject) + + local neutralPlayers = {} + for i, player in ipairs(players) do + assignToTeam(player) end end - wait(1/30) - --do a base update, just ot be sure - BaseUpdate() - wait(1/30) - - end -end ---]] - --quick fix running logic, PLEASE LET ME REPLACE LATER - --Spawn(EnsureValidity) - + removePlayerFunction = function(player) + if playerTable[player] then + clearTableEntry(player, playerTable[player]) + + ArrayRemove(scrollOrderSmall, playerTable[player].MainObjectSmall) + ArrayRemove(scrollOrderBig, playerTable[player].MainObjectBig) + + playerTable[player] = nil + recalculateSmallPlayerListSize(smallFrame) + end + end + recreatePlayerFunction = function(player) + removePlayerFunction(player) + + local playerObject = buildPlayerObject(player, numStatColumns, "Small") + table.insert(scrollOrderSmall, playerObject) + robloxLock(playerObject) + playerObject.Parent = scrollFrameSmall + + playerObject = buildPlayerObject(player, currentStatCount, "Big") + table.insert(scrollOrderBig, playerObject) + robloxLock(playerObject) + playerObject.Parent = scrollFrameBig + + local isTeam, isScore = getBoardTypeInfo() + if isTeam then + assignToTeam(player) + end + + sortPlayerListsFunction() + recalculateSmallPlayerListSize(smallFrame) + end + + if screenResizeCon then screenResizeCon:disconnect() end + screenResizeCon = screen.Changed:connect( + function(prop) + if prop == "AbsoluteSize" then + wait() + recalculateSmallPlayerListSize(smallFrame) + end + end) + + sortPlayerListsFunction = function() + orderScrollList(scrollOrderSmall, "MainObjectSmall", scrollFrameSmall) + recalculateScrollSmall() + createAlternatingRows(scrollOrderSmall) + + orderScrollList(scrollOrderBig, "MainObjectBig", 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(script.Parent, determineBoardType()) + debounceTeamsChanged = false + end + + + local checkIfBoardChanged = function() + local newBoardType, numStats = determineBoardType() + if newBoardType ~= currentBoardType or numStats ~= currentStatCount then + rebuildBoard(script.Parent, newBoardType, numStats) + end + end + + local function buildPlayerList() + waitForChild(game, "Players") + waitForProperty(game.Players, "LocalPlayer") + + local 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 = true + end + + local teams = game:GetService("Teams") + if teams then + local teamConnections = {} + + teams.ChildAdded:connect( + function(child) + if child:IsA("Team") then + teamsChanged() + teamConnections[child] = child.Changed:connect( + function(prop) + if prop == "TeamColor" or prop == "Name" then + --Rebuild when things change + teamsChanged() + end + end) + end + end) + teams.ChildRemoved:connect( + function(child) + if child:IsA("Team") then + if teamConnections[child] then + teamConnections[child]:disconnect() + teamConnections[child] = nil + end + teamsChanged() + end + end) + end + + game.Players.ChildAdded:connect( + function(player) + if player:IsA("Player") then + addPlayerFunction(player) + end + end) + + game.Players.ChildRemoved:connect( + function(player) + if player:IsA("Player") then + if removePlayerFunction then + removePlayerFunction(player) + end + end + end) + + rebuildBoard(script.Parent, determineBoardType()) + game.GuiService.ShowLegacyPlayerList = false + + game.GuiService:AddKey("\t") + local lastTime = nil + game.GuiService.KeyPressed:connect( + function(key) + if key == "\t" then + local modalCheck, isModal = pcall(function() return game.GuiService.IsModalDialog end) + if modalCheck == false or (modalCheck and isModal == false) then + local currentTime = time() + if lastTime == nil or currentTime - lastTime > 0.4 then + lastTime = currentTime + toggleBigWindow() + end + end + end + end) + + delay(0, + function() + while true do + wait(5) + checkIfBoardChanged() + end + end) + end + + if game.CoreGui.Version >= 2 then + buildPlayerList() + end +end diff --git a/public/asset/12 b/public/asset/12 index 0314981..cded2ee 100644 --- a/public/asset/12 +++ b/public/asset/12 @@ -1,875 +1,363 @@ -%12% --- This script creates almost all gui elements found in the backpack (warning: there are a lot!) --- TODO: automate this process - -if game.CoreGui.Version < 3 then return end -- peace out if we aren't using the right client - -local gui = script.Parent - --- A couple of necessary functions -local function waitForChild(instance, name) - while not instance:FindFirstChild(name) do - instance.ChildAdded:wait() - end -end -local function waitForProperty(instance, property) - while not instance[property] do - instance.Changed:wait() - end -end - -local function IsTouchDevice() - local touchEnabled = false - pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end) - return touchEnabled -end - -local function IsPhone() - if gui.AbsoluteSize.Y <= 320 then - return true - end - return false -end - -waitForChild(game,"Players") -waitForProperty(game.Players,"LocalPlayer") -local player = game.Players.LocalPlayer - --- First up is the current loadout -local CurrentLoadout = Instance.new("Frame") -CurrentLoadout.Name = "CurrentLoadout" -CurrentLoadout.Position = UDim2.new(0.5, -300, 1, -85) -CurrentLoadout.Size = UDim2.new(0, 600, 0, 54) -CurrentLoadout.BackgroundTransparency = 1 -CurrentLoadout.RobloxLocked = true -CurrentLoadout.Parent = gui - -local CLBackground = Instance.new('ImageLabel') -CLBackground.Name = 'Background'; -CLBackground.Size = UDim2.new(1.2, 0, 1.2, 0); -CLBackground.Image = "rbxasset://Textures/IPadInGameGUIToolbar.png" -CLBackground.BackgroundTransparency = 1.0; -CLBackground.Position = UDim2.new(-0.1, 0, -0.1, 0); -CLBackground.ZIndex = 0.0; -CLBackground.Parent = CurrentLoadout -CLBackground.Visible = false - -local BackgroundUp = Instance.new('ImageLabel') -BackgroundUp.Size = UDim2.new(1, 0, 0.025, 1) -BackgroundUp.Position = UDim2.new(0, 0, 0, 0) -BackgroundUp.Image = 'rbxasset://Textures/IPadInGameGUIToolbarTop03.png' -BackgroundUp.BackgroundTransparency = 1.0 -BackgroundUp.Parent = CLBackground - -local Debounce = Instance.new("BoolValue") -Debounce.Name = "Debounce" -Debounce.RobloxLocked = true -Debounce.Parent = CurrentLoadout - -local BackpackButton = Instance.new("ImageButton") -BackpackButton.RobloxLocked = true -BackpackButton.Visible = false -BackpackButton.Name = "BackpackButton" -BackpackButton.BackgroundTransparency = 1 -BackpackButton.Image = "rbxasset://Textures/IPadInGameGUIToolbarBkpkTabTopV3.png" -BackpackButton.Position = UDim2.new(0.5, -60, 1, -108) -BackpackButton.Size = UDim2.new(0, 120, 0, 18) -waitForChild(gui,"ControlFrame") -BackpackButton.Parent = gui.ControlFrame - -local NumSlots = 9 - -if IsPhone() then - NumSlots = 3 - CurrentLoadout.Size = UDim2.new(0, 180, 0, 54) - CurrentLoadout.Position = UDim2.new(0.5, -90, 1, -85) -end - - -for i = 0, NumSlots do - local slotFrame = Instance.new("Frame") - slotFrame.RobloxLocked = true - slotFrame.BackgroundColor3 = Color3.new(0,0,0) - slotFrame.BackgroundTransparency = 1 - slotFrame.BorderColor3 = Color3.new(1, 1, 1) - slotFrame.Name = "Slot" .. tostring(i) - slotFrame.ZIndex = 4.0 - if i == 0 then - slotFrame.Position = UDim2.new(0.9, 0, 0, 0) - else - slotFrame.Position = UDim2.new((i - 1) * 0.1, (i-1)* 6,0,0) - end - - - slotFrame.Size = UDim2.new(0, 54, 1, 0) - slotFrame.Parent = CurrentLoadout - - if gui.AbsoluteSize.Y <= 320 then - slotFrame.Position = UDim2.new(0, (i-1)* 60, 0, -50) - print('Well got here', slotFrame, slotFrame.Position.X.Scale, slotFrame.Position.X.Offset) - end - if gui.AbsoluteSize.Y <= 320 and i == 0 then - slotFrame:Destroy() - end -end - -local TempSlot = Instance.new("ImageButton") -TempSlot.Name = "TempSlot" -TempSlot.Active = true -TempSlot.Size = UDim2.new(1,0,1,0) -TempSlot.BackgroundTransparency = 1.0 -TempSlot.Style = 'Custom' -TempSlot.Visible = false -TempSlot.RobloxLocked = true -TempSlot.Parent = CurrentLoadout -TempSlot.ZIndex = 4.0 - - local slotBackground = Instance.new('ImageLabel') - slotBackground.Name = 'Background' - slotBackground.BackgroundTransparency = 1.0 - slotBackground.Image = 'rbxasset://Textures/IPadInGameGUITool.png' - slotBackground.Size = UDim2.new(1, 0, 1, 0) - slotBackground.Parent = TempSlot - - local HighLight = Instance.new('ImageLabel') - HighLight.Name = 'Highlight' - HighLight.BackgroundTransparency = 1.0 - HighLight.Image = 'http://www.morblox.us/asset/?id=97643886' - HighLight.Size = UDim2.new(1, 0, 1, 0) - --HighLight.Parent = TempSlot - HighLight.Visible = false - - -- TempSlot Children - local GearReference = Instance.new("ObjectValue") - GearReference.Name = "GearReference" - GearReference.RobloxLocked = true - GearReference.Parent = TempSlot - - - local ToolTipLabel = Instance.new("TextLabel") - ToolTipLabel.Name = "ToolTipLabel" - ToolTipLabel.RobloxLocked = true - ToolTipLabel.Text = "" - ToolTipLabel.BackgroundTransparency = 0.5 - ToolTipLabel.BorderSizePixel = 0 - ToolTipLabel.Visible = false - ToolTipLabel.TextColor3 = Color3.new(1,1,1) - ToolTipLabel.BackgroundColor3 = Color3.new(0,0,0) - ToolTipLabel.TextStrokeTransparency = 0 - ToolTipLabel.Font = Enum.Font.ArialBold - ToolTipLabel.FontSize = Enum.FontSize.Size14 - --ToolTipLabel.TextWrap = true - ToolTipLabel.Size = UDim2.new(1,60,0,20) - ToolTipLabel.Position = UDim2.new(0,-30,0,-30) - ToolTipLabel.Parent = TempSlot - - - local Kill = Instance.new("BoolValue") - Kill.Name = "Kill" - Kill.RobloxLocked = true - Kill.Parent = TempSlot - - local GearImage = Instance.new("ImageLabel") - GearImage.Name = "GearImage" - GearImage.BackgroundTransparency = 1 - GearImage.Position = UDim2.new(0, 0, 0, 0) - GearImage.Size = UDim2.new(1, 0, 1, 0) - GearImage.ZIndex = 5.0 - GearImage.RobloxLocked = true - GearImage.Parent = TempSlot - - local SlotNumber = Instance.new("TextLabel") - SlotNumber.Name = "SlotNumber" - SlotNumber.BackgroundTransparency = 1 - SlotNumber.BorderSizePixel = 0 - SlotNumber.Font = Enum.Font.ArialBold - SlotNumber.FontSize = Enum.FontSize.Size18 - SlotNumber.Position = UDim2.new(0, 0, 0, 0) - SlotNumber.Size = UDim2.new(0,10,0,15) - SlotNumber.TextColor3 = Color3.new(1,1,1) - SlotNumber.TextTransparency = 0 - SlotNumber.TextXAlignment = Enum.TextXAlignment.Left - SlotNumber.TextYAlignment = Enum.TextYAlignment.Bottom - SlotNumber.RobloxLocked = true - SlotNumber.Parent = TempSlot - SlotNumber.ZIndex = 5 - - if IsTouchDevice() then - SlotNumber.Visible = false - end - - local SlotNumberDownShadow = SlotNumber:Clone() - SlotNumberDownShadow.Name = "SlotNumberDownShadow" - SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0) - SlotNumberDownShadow.Position = UDim2.new(0, 1, 0, -1) - SlotNumberDownShadow.Parent = TempSlot - SlotNumberDownShadow.ZIndex = 2 - - local SlotNumberUpShadow = SlotNumberDownShadow:Clone() - SlotNumberUpShadow.Name = "SlotNumberUpShadow" - SlotNumberUpShadow.Position = UDim2.new(0, -1, 0, -1) - SlotNumberUpShadow.Parent = TempSlot - - local GearText = Instance.new("TextLabel") - GearText.RobloxLocked = true - GearText.Name = "GearText" - GearText.BackgroundTransparency = 1 - GearText.Font = Enum.Font.Arial - GearText.FontSize = Enum.FontSize.Size14 - GearText.Position = UDim2.new(0,-8,0,-8) - GearText.Size = UDim2.new(1,16,1,16) - GearText.Text = "" - GearText.TextColor3 = Color3.new(1,1,1) - GearText.TextWrap = true - GearText.Parent = TempSlot - GearText.ZIndex = 5.0 - ---- Great, now lets make the inventory! - -local Backpack = Instance.new("Frame") -Backpack.RobloxLocked = true -Backpack.Visible = false -Backpack.Name = "Backpack" -Backpack.Position = UDim2.new(0.5, 0, 0.5, 0) -Backpack.BackgroundColor3 = Color3.new(32/255, 32/255, 32/255) -Backpack.BackgroundTransparency = 0.0 -Backpack.BorderSizePixel = 0 -Backpack.Parent = gui -Backpack.Active = true - - -- Backpack Children - local SwapSlot = Instance.new("BoolValue") - SwapSlot.RobloxLocked = true - SwapSlot.Name = "SwapSlot" - SwapSlot.Parent = Backpack - - -- SwapSlot Children - local Slot = Instance.new("IntValue") - Slot.RobloxLocked = true - Slot.Name = "Slot" - Slot.Parent = SwapSlot - - local GearButton = Instance.new("ObjectValue") - GearButton.RobloxLocked = true - GearButton.Name = "GearButton" - GearButton.Parent = SwapSlot - - local Tabs = Instance.new("Frame") - Tabs.Name = "Tabs" - Tabs.Visible = false - Tabs.Active = false - Tabs.RobloxLocked = true - Tabs.BackgroundColor3 = Color3.new(0,0,0) - Tabs.BackgroundTransparency = 0.08 - Tabs.BorderSizePixel = 0 - Tabs.Position = UDim2.new(0,0,-0.1,-4) - Tabs.Size = UDim2.new(1,0,0.1,4) - Tabs.Parent = Backpack - - -- Tabs Children - - local tabLine = Instance.new("Frame") - tabLine.RobloxLocked = true - tabLine.Name = "TabLine" - tabLine.BackgroundColor3 = Color3.new(53/255, 53/255, 53/255) - tabLine.BorderSizePixel = 0 - tabLine.Position = UDim2.new(0,5,1,-4) - tabLine.Size = UDim2.new(1,-10,0,4) - tabLine.ZIndex = 2 - tabLine.Parent = Tabs - - local InventoryButton = Instance.new("TextButton") - InventoryButton.RobloxLocked = true - InventoryButton.Name = "InventoryButton" - InventoryButton.Size = UDim2.new(0,60,0,30) - InventoryButton.Position = UDim2.new(0,7,1,-31) - InventoryButton.BackgroundColor3 = Color3.new(1,1,1) - InventoryButton.BorderColor3 = Color3.new(1,1,1) - InventoryButton.Font = Enum.Font.ArialBold - InventoryButton.FontSize = Enum.FontSize.Size18 - InventoryButton.Text = "Gear" - InventoryButton.AutoButtonColor = false - InventoryButton.TextColor3 = Color3.new(0,0,0) - InventoryButton.Selected = true - InventoryButton.Active = true - InventoryButton.ZIndex = 3 - InventoryButton.Parent = Tabs - - if game.CoreGui.Version >= 8 then - local WardrobeButton = Instance.new("TextButton") - WardrobeButton.RobloxLocked = true - WardrobeButton.Name = "WardrobeButton" - WardrobeButton.Size = UDim2.new(0,90,0,30) - WardrobeButton.Position = UDim2.new(0,77,1,-31) - WardrobeButton.BackgroundColor3 = Color3.new(0,0,0) - WardrobeButton.BorderColor3 = Color3.new(1,1,1) - WardrobeButton.Font = Enum.Font.ArialBold - WardrobeButton.FontSize = Enum.FontSize.Size18 - WardrobeButton.Text = "Wardrobe" - WardrobeButton.AutoButtonColor = false - WardrobeButton.TextColor3 = Color3.new(1,1,1) - WardrobeButton.Selected = false - WardrobeButton.Active = true - WardrobeButton.Parent = Tabs - end - - local closeButton = Instance.new("TextButton") - closeButton.RobloxLocked = true - closeButton.Name = "CloseButton" - closeButton.Font = Enum.Font.ArialBold - closeButton.FontSize = Enum.FontSize.Size24 - closeButton.Position = UDim2.new(1,-33,0,4) - closeButton.Size = UDim2.new(0,30,0,30) - closeButton.Style = Enum.ButtonStyle.RobloxButton - closeButton.Text = "" - closeButton.TextColor3 = Color3.new(1,1,1) - closeButton.Parent = Tabs - closeButton.Modal = true - - --closeButton child - local XImage = Instance.new("ImageLabel") - XImage.RobloxLocked = true - XImage.Name = "XImage" - game:GetService("ContentProvider"):Preload("http://www.morblox.us/asset/?id=75547445") - XImage.Image = "http://www.morblox.us/asset/?id=75547445" --TODO: move to rbxasset - XImage.BackgroundTransparency = 1 - XImage.Position = UDim2.new(-.25,-1,-.25,-1) - XImage.Size = UDim2.new(1.5,2,1.5,2) - XImage.ZIndex = 2 - XImage.Parent = closeButton - - -- Generic Search gui used across backpack - local SearchFrame = Instance.new("Frame") - SearchFrame.RobloxLocked = true - SearchFrame.Name = "SearchFrame" - SearchFrame.BackgroundTransparency = 1 - SearchFrame.Position = UDim2.new(1,-220,0,2) - SearchFrame.Size = UDim2.new(0,220,0,24) - SearchFrame.Parent = Backpack - - -- SearchFrame Children - local SearchButton = Instance.new("ImageButton") - SearchButton.RobloxLocked = true - SearchButton.Name = "SearchButton" - SearchButton.Size = UDim2.new(0,25,0,25) - SearchButton.BackgroundTransparency = 1 - SearchButton.Image = "rbxasset://textures/ui/SearchIcon.png" - SearchButton.Parent = SearchFrame - - local SearchBoxFrame = Instance.new("TextButton") - SearchBoxFrame.RobloxLocked = true - SearchBoxFrame.Position = UDim2.new(0,25,0,0) - SearchBoxFrame.Size = UDim2.new(1,-28,0,26) - SearchBoxFrame.Name = "SearchBoxFrame" - SearchBoxFrame.Text = "" - SearchBoxFrame.Style = Enum.ButtonStyle.RobloxButton - SearchBoxFrame.Parent = SearchFrame - - -- SearchBoxFrame Children - local SearchBox = Instance.new("TextBox") - SearchBox.RobloxLocked = true - SearchBox.Name = "SearchBox" - SearchBox.BackgroundTransparency = 1 - SearchBox.Font = Enum.Font.ArialBold - SearchBox.FontSize = Enum.FontSize.Size12 - SearchBox.Position = UDim2.new(0,-5,0,-5) - SearchBox.Size = UDim2.new(1,10,1,10) - SearchBox.TextColor3 = Color3.new(1,1,1) - SearchBox.TextXAlignment = Enum.TextXAlignment.Left - SearchBox.ZIndex = 2 - SearchBox.TextWrap = true - SearchBox.Text = "Search..." - SearchBox.Parent = SearchBoxFrame - - - local ResetButton = Instance.new("TextButton") - ResetButton.RobloxLocked = true - ResetButton.Visible = false - ResetButton.Name = "ResetButton" - ResetButton.Position = UDim2.new(1,-26,0,3) - ResetButton.Size = UDim2.new(0,20,0,20) - ResetButton.Style = Enum.ButtonStyle.RobloxButtonDefault - ResetButton.Text = "X" - ResetButton.TextColor3 = Color3.new(1,1,1) - ResetButton.Font = Enum.Font.ArialBold - ResetButton.FontSize = Enum.FontSize.Size18 - ResetButton.ZIndex = 3 - ResetButton.Parent = SearchFrame - -------------------------------- GEAR ------------------------------------------------------- - local Gear = Instance.new("Frame") - Gear.Name = "Gear" - Gear.RobloxLocked = true - Gear.BackgroundTransparency = 1 - Gear.Size = UDim2.new(1,0,1,0) - Gear.Parent = Backpack - - -- Gear Children - local AssetsList = Instance.new("Frame") - AssetsList.RobloxLocked = true - AssetsList.Name = "AssetsList" - AssetsList.BackgroundTransparency = 1 - AssetsList.Size = UDim2.new(0.2,0,1,0) - AssetsList.Style = Enum.FrameStyle.RobloxSquare - AssetsList.Visible = false - AssetsList.Parent = Gear - - local GearGrid = Instance.new("Frame") - GearGrid.RobloxLocked = true - GearGrid.Name = "GearGrid" - GearGrid.Size = UDim2.new(0.95, 0, 1, 0) - GearGrid.BackgroundTransparency = 1 - GearGrid.Parent = Gear - - - local GearButton = Instance.new("ImageButton") - GearButton.RobloxLocked = true - GearButton.Visible = false - GearButton.Name = "GearButton" - GearButton.Size = UDim2.new(0, 54, 0, 54) - GearButton.Style = 'Custom' - GearButton.Parent = GearGrid - GearButton.BackgroundTransparency = 1.0 - - local slotBackground = Instance.new('ImageLabel') - slotBackground.Name = 'Background' - slotBackground.BackgroundTransparency = 1.0 - slotBackground.Image = 'http://www.morblox.us/asset/?id=97613075' - slotBackground.Size = UDim2.new(1, 0, 1, 0) - slotBackground.Parent = GearButton - - - -- GearButton Children - local GearReference = Instance.new("ObjectValue") - GearReference.RobloxLocked = true - GearReference.Name = "GearReference" - GearReference.Parent = GearButton - - local GreyOutButton = Instance.new("Frame") - GreyOutButton.RobloxLocked = true - GreyOutButton.Name = "GreyOutButton" - GreyOutButton.BackgroundTransparency = 0.5 - GreyOutButton.Size = UDim2.new(1,0,1,0) - GreyOutButton.Active = true - GreyOutButton.Visible = false - GreyOutButton.ZIndex = 3 - GreyOutButton.Parent = GearButton - - local GearText = Instance.new("TextLabel") - GearText.RobloxLocked = true - GearText.Name = "GearText" - GearText.BackgroundTransparency = 1 - GearText.Font = Enum.Font.Arial - GearText.FontSize = Enum.FontSize.Size14 - GearText.Position = UDim2.new(0,-8,0,-8) - GearText.Size = UDim2.new(1,16,1,16) - GearText.Text = "" - GearText.ZIndex = 2 - GearText.TextColor3 = Color3.new(1,1,1) - GearText.TextWrap = true - GearText.Parent = GearButton - - local GearGridScrollingArea = Instance.new("Frame") - GearGridScrollingArea.RobloxLocked = true - GearGridScrollingArea.Name = "GearGridScrollingArea" - GearGridScrollingArea.Position = UDim2.new(1, -19, 0, 35) - GearGridScrollingArea.Size = UDim2.new(0, 17, 1, -45) - GearGridScrollingArea.BackgroundTransparency = 1 - GearGridScrollingArea.Parent = Gear - - local GearLoadouts = Instance.new("Frame") - GearLoadouts.RobloxLocked = true - GearLoadouts.Name = "GearLoadouts" - GearLoadouts.BackgroundTransparency = 1 - GearLoadouts.Position = UDim2.new(0.7,23,0.5,1) - GearLoadouts.Size = UDim2.new(0.3,-23,0.5,-1) - GearLoadouts.Parent = Gear - GearLoadouts.Visible = false - - -- GearLoadouts Children - local GearLoadoutsHeader = Instance.new("Frame") - GearLoadoutsHeader.RobloxLocked = true - GearLoadoutsHeader.Name = "GearLoadoutsHeader" - GearLoadoutsHeader.BackgroundColor3 = Color3.new(0,0,0) - GearLoadoutsHeader.BackgroundTransparency = 0.2 - GearLoadoutsHeader.BorderColor3 = Color3.new(1,0,0) - GearLoadoutsHeader.Size = UDim2.new(1,2,0.15,-1) - GearLoadoutsHeader.Parent = GearLoadouts - - -- GearLoadoutsHeader Children - local LoadoutsHeaderText = Instance.new("TextLabel") - LoadoutsHeaderText.RobloxLocked = true - LoadoutsHeaderText.Name = "LoadoutsHeaderText" - LoadoutsHeaderText.BackgroundTransparency = 1 - LoadoutsHeaderText.Font = Enum.Font.ArialBold - LoadoutsHeaderText.FontSize = Enum.FontSize.Size18 - LoadoutsHeaderText.Size = UDim2.new(1,0,1,0) - LoadoutsHeaderText.Text = "Loadouts" - LoadoutsHeaderText.TextColor3 = Color3.new(1,1,1) - LoadoutsHeaderText.Parent = GearLoadoutsHeader - - local GearLoadoutsScrollingArea = GearGridScrollingArea:clone() - GearLoadoutsScrollingArea.RobloxLocked = true - GearLoadoutsScrollingArea.Name = "GearLoadoutsScrollingArea" - GearLoadoutsScrollingArea.Position = UDim2.new(1,-15,0.15,2) - GearLoadoutsScrollingArea.Size = UDim2.new(0,17,0.85,-2) - GearLoadoutsScrollingArea.Parent = GearLoadouts - - local LoadoutsList = Instance.new("Frame") - LoadoutsList.RobloxLocked = true - LoadoutsList.Name = "LoadoutsList" - LoadoutsList.Position = UDim2.new(0,0,0.15,2) - LoadoutsList.Size = UDim2.new(1,-17,0.85,-2) - LoadoutsList.Style = Enum.FrameStyle.RobloxSquare - LoadoutsList.Parent = GearLoadouts - - local GearPreview = Instance.new("Frame") - GearPreview.RobloxLocked = true - GearPreview.Name = "GearPreview" - GearPreview.Position = UDim2.new(0.7,23,0,0) - GearPreview.Size = UDim2.new(0.3,-28,0.5,-1) - GearPreview.BackgroundTransparency = 1 - GearPreview.ZIndex = 7 - GearPreview.Parent = Gear - - -- GearPreview Children - local GearStats = Instance.new("Frame") - GearStats.RobloxLocked = true - GearStats.Name = "GearStats" - GearStats.BackgroundTransparency = 1 - GearStats.Position = UDim2.new(0,0,0.75,0) - GearStats.Size = UDim2.new(1,0,0.25,0) - GearStats.ZIndex = 8 - GearStats.Parent = GearPreview - - -- GearStats Children - local GearName = Instance.new("TextLabel") - GearName.RobloxLocked = true - GearName.Name = "GearName" - GearName.BackgroundTransparency = 1 - GearName.Font = Enum.Font.ArialBold - GearName.FontSize = Enum.FontSize.Size18 - GearName.Position = UDim2.new(0,-3,0,0) - GearName.Size = UDim2.new(1,6,1,5) - GearName.Text = "" - GearName.TextColor3 = Color3.new(1,1,1) - GearName.TextWrap = true - GearName.ZIndex = 9 - GearName.Parent = GearStats - - local GearImage = Instance.new("ImageLabel") - GearImage.RobloxLocked = true - GearImage.Name = "GearImage" - GearImage.Image = "" - GearImage.BackgroundTransparency = 1 - GearImage.Position = UDim2.new(0.125,0,0,0) - GearImage.Size = UDim2.new(0.75,0,0.75,0) - GearImage.ZIndex = 8 - GearImage.Parent = GearPreview - - --GearImage Children - local GearIcons = Instance.new("Frame") - GearIcons.BackgroundColor3 = Color3.new(0,0,0) - GearIcons.BackgroundTransparency = 0.5 - GearIcons.BorderSizePixel = 0 - GearIcons.RobloxLocked = true - GearIcons.Name = "GearIcons" - GearIcons.Position = UDim2.new(0.4,2,0.85,-2) - GearIcons.Size = UDim2.new(0.6,0,0.15,0) - GearIcons.Visible = false - GearIcons.ZIndex = 9 - GearIcons.Parent = GearImage - - -- GearIcons Children - local GenreImage = Instance.new("ImageLabel") - GenreImage.RobloxLocked = true - GenreImage.Name = "GenreImage" - GenreImage.BackgroundColor3 = Color3.new(102/255,153/255,1) - GenreImage.BackgroundTransparency = 0.5 - GenreImage.BorderSizePixel = 0 - GenreImage.Size = UDim2.new(0.25,0,1,0) - GenreImage.Parent = GearIcons - - local AttributeOneImage = GenreImage:clone() - AttributeOneImage.RobloxLocked = true - AttributeOneImage.Name = "AttributeOneImage" - AttributeOneImage.BackgroundColor3 = Color3.new(1,51/255,0) - AttributeOneImage.Position = UDim2.new(0.25,0,0,0) - AttributeOneImage.Parent = GearIcons - - local AttributeTwoImage = GenreImage:clone() - AttributeTwoImage.RobloxLocked = true - AttributeTwoImage.Name = "AttributeTwoImage" - AttributeTwoImage.BackgroundColor3 = Color3.new(153/255,1,153/255) - AttributeTwoImage.Position = UDim2.new(0.5,0,0,0) - AttributeTwoImage.Parent = GearIcons - - local AttributeThreeImage = GenreImage:clone() - AttributeThreeImage.RobloxLocked = true - AttributeThreeImage.Name = "AttributeThreeImage" - AttributeThreeImage.BackgroundColor3 = Color3.new(0,0.5,0.5) - AttributeThreeImage.Position = UDim2.new(0.75,0,0,0) - AttributeThreeImage.Parent = GearIcons - -------------------------------- WARDROBE ------------------------------------------------------- - if game.CoreGui.Version < 8 then - -- no need for this to stick around, we aren't ready for wardrobe - script:remove() - return - end - - local function makeCharFrame(frameName, parent) - local frame = Instance.new("Frame") - frame.RobloxLocked = true - frame.Size = UDim2.new(1,0,1,-70) - frame.Position = UDim2.new(0,0,0,20) - frame.Name = frameName - frame.BackgroundTransparency = 1 - frame.Parent = parent - frame.Visible = false - return frame - end - local function makeZone( zoneName, image, size, position, parent ) - local zone = Instance.new("ImageLabel") - zone.RobloxLocked = true - zone.Name = zoneName - zone.Image = image - zone.Size = size - zone.BackgroundTransparency = 1 - zone.Position = position - zone.Parent = parent - return zone - end - local function makeStyledButton( buttonName, size, position, parent, buttonStyle ) - local button = Instance.new("ImageButton") - button.RobloxLocked = true - button.Name = buttonName - button.Size = size - button.Position = position - if buttonStyle then - button.Style = buttonStyle - else - button.BackgroundColor3 = Color3.new(0,0,0) - button.BorderColor3 = Color3.new(1,1,1) - end - button.Parent = parent - return button - end - local function makeTextLabel( TextLabelName,text,position,parent ) - local label = Instance.new("TextLabel") - label.RobloxLocked = true - label.BackgroundTransparency = 1 - label.Size = UDim2.new(0,32,0,14) - label.Name = TextLabelName - label.Font = Enum.Font.Arial - label.TextColor3 = Color3.new(1,1,1) - label.FontSize = Enum.FontSize.Size14 - label.Text = text - label.Position = position - label.Parent = parent - end - - - local Wardrobe = Instance.new("Frame") - Wardrobe.Name = "Wardrobe" - Wardrobe.RobloxLocked = true - Wardrobe.BackgroundTransparency = 1 - Wardrobe.Visible = false - Wardrobe.Size = UDim2.new(1,0,1,0) - Wardrobe.Parent = Backpack - - local AssetList = Instance.new("Frame") - AssetList.RobloxLocked = true - AssetList.Name = "AssetList" - AssetList.Position = UDim2.new(0,4,0,5) - AssetList.Size = UDim2.new(0,85,1,-5) - AssetList.BackgroundTransparency = 1 - AssetList.Visible = true - AssetList.Parent = Wardrobe - - local PreviewAssetFrame = Instance.new("Frame") - PreviewAssetFrame.RobloxLocked = true - PreviewAssetFrame.Name = "PreviewAssetFrame" - PreviewAssetFrame.BackgroundTransparency = 1 - PreviewAssetFrame.Position = UDim2.new(1,-240,0,30) - PreviewAssetFrame.Size = UDim2.new(0,250,0,250) - PreviewAssetFrame.Parent = Wardrobe - - local PreviewAssetBacking = Instance.new("TextButton") - PreviewAssetBacking.RobloxLocked = true - PreviewAssetBacking.Name = "PreviewAssetBacking" - PreviewAssetBacking.Active = false - PreviewAssetBacking.Text = "" - PreviewAssetBacking.AutoButtonColor = false - PreviewAssetBacking.Size = UDim2.new(1,0,1,0) - PreviewAssetBacking.Style = Enum.ButtonStyle.RobloxButton - PreviewAssetBacking.Visible = false - PreviewAssetBacking.ZIndex = 9 - PreviewAssetBacking.Parent = PreviewAssetFrame - - local PreviewAssetImage = Instance.new("ImageLabel") - PreviewAssetImage.RobloxLocked = true - PreviewAssetImage.Name = "PreviewAssetImage" - PreviewAssetImage.BackgroundTransparency = 0.8 - PreviewAssetImage.Position = UDim2.new(0.5,-100,0,0) - PreviewAssetImage.Size = UDim2.new(0,200,0,200) - PreviewAssetImage.BorderSizePixel = 0 - PreviewAssetImage.ZIndex = 10 - PreviewAssetImage.Parent = PreviewAssetBacking - - local AssetNameLabel = Instance.new("TextLabel") - AssetNameLabel.Name = "AssetNameLabel" - AssetNameLabel.RobloxLocked = true - AssetNameLabel.BackgroundTransparency = 1 - AssetNameLabel.Position = UDim2.new(0,0,1,-20) - AssetNameLabel.Size = UDim2.new(0.5,0,0,24) - AssetNameLabel.ZIndex = 10 - AssetNameLabel.Font = Enum.Font.Arial - AssetNameLabel.Text = "" - AssetNameLabel.TextColor3 = Color3.new(1,1,1) - AssetNameLabel.TextScaled = true - AssetNameLabel.Parent = PreviewAssetBacking - - local AssetTypeLabel = AssetNameLabel:clone() - AssetTypeLabel.RobloxLocked = true - AssetTypeLabel.Name = "AssetTypeLabel" - AssetTypeLabel.TextScaled = false - AssetTypeLabel.FontSize = Enum.FontSize.Size18 - AssetTypeLabel.Position = UDim2.new(0.5,3,1,-20) - AssetTypeLabel.Parent = PreviewAssetBacking - - - - local PreviewButton = Instance.new("TextButton") - PreviewButton.RobloxLocked = true - PreviewButton.Name = "PreviewButton" - PreviewButton.Text = "Rotate" - PreviewButton.BackgroundColor3 = Color3.new(0,0,0) - PreviewButton.BackgroundTransparency = 0.5 - PreviewButton.BorderColor3 = Color3.new(1,1,1) - PreviewButton.Position = UDim2.new(1.2,-62,1,-50) - PreviewButton.Size = UDim2.new(0,125,0,50) - PreviewButton.Font = Enum.Font.ArialBold - PreviewButton.FontSize = Enum.FontSize.Size24 - PreviewButton.TextColor3 = Color3.new(1,1,1) - PreviewButton.TextWrapped = true - PreviewButton.TextStrokeTransparency = 0 - PreviewButton.Parent = Wardrobe - - local CharacterPane = Instance.new("Frame") - CharacterPane.RobloxLocked = true - CharacterPane.Name = "CharacterPane" - CharacterPane.Position = UDim2.new(1,-220,0,32) - CharacterPane.Size = UDim2.new(0,220,1,-40) - CharacterPane.BackgroundTransparency = 1 - CharacterPane.Visible = true - CharacterPane.Parent = Wardrobe - - --CharacterPane Children - local FaceFrame = makeCharFrame("FacesFrame", CharacterPane) - game:GetService("ContentProvider"):Preload("http://www.morblox.us/asset/?id=75460621") - makeZone("FaceZone","http://www.morblox.us/asset/?id=75460621",UDim2.new(0,157,0,137),UDim2.new(0.5,-78,0.5,-68),FaceFrame) - makeStyledButton("Face",UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-135),FaceFrame) - - local HeadFrame = makeCharFrame("HeadsFrame", CharacterPane) - makeZone("FaceZone","http://www.morblox.us/asset/?id=75460621",UDim2.new(0,157,0,137),UDim2.new(0.5,-78,0.5,-68),HeadFrame) - makeStyledButton("Head",UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-135),HeadFrame) - - local HatsFrame = makeCharFrame("HatsFrame", CharacterPane) - game:GetService("ContentProvider"):Preload("http://www.morblox.us/asset/?id=75457888") - local HatsZone = makeZone("HatsZone","http://www.morblox.us/asset/?id=75457888",UDim2.new(0,186,0,184),UDim2.new(0.5,-93,0.5,-100), HatsFrame) - makeStyledButton("Hat1Button",UDim2.new(0,64,0,64),UDim2.new(0,-1,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton) - makeStyledButton("Hat2Button",UDim2.new(0,64,0,64),UDim2.new(0,63,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton) - makeStyledButton("Hat3Button",UDim2.new(0,64,0,64),UDim2.new(0,127,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton) - - local PantsFrame = makeCharFrame("PantsFrame", CharacterPane) - game:GetService("ContentProvider"):Preload("http://www.morblox.us/asset/?id=75457920") - makeZone("PantsZone","http://www.morblox.us/asset/?id=75457920",UDim2.new(0,121,0,99),UDim2.new(0.5,-60,0.5,-100),PantsFrame) - - local pantFrame = Instance.new("Frame") - pantFrame.RobloxLocked = true - pantFrame.Size = UDim2.new(0,25,0,56) - pantFrame.Position = UDim2.new(0.5,-26,0.5,0) - pantFrame.BackgroundColor3 = Color3.new(0,0,0) - pantFrame.BorderColor3 = Color3.new(1,1,1) - pantFrame.Name = "PantFrame" - pantFrame.Parent = PantsFrame - - local otherPantFrame = pantFrame:clone() - otherPantFrame.Position = UDim2.new(0.5,3,0.5,0) - otherPantFrame.RobloxLocked = true - otherPantFrame.Parent = PantsFrame - - local CurrentPants = Instance.new("ImageButton") - CurrentPants.RobloxLocked = true - CurrentPants.BackgroundTransparency = 1 - CurrentPants.ZIndex = 2 - CurrentPants.Name = "CurrentPants" - CurrentPants.Position = UDim2.new(0.5,-31,0.5,-4) - CurrentPants.Size = UDim2.new(0,54,0,59) - CurrentPants.Parent = PantsFrame - - local MeshFrame = makeCharFrame("PackagesFrame", CharacterPane) - local torsoButton = makeStyledButton("TorsoMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton) - makeTextLabel("TorsoLabel","Torso",UDim2.new(0.5,-16,0,-25),torsoButton) - local leftLegButton = makeStyledButton("LeftLegMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,0,0.5,-25),MeshFrame,Enum.ButtonStyle.RobloxButton) - makeTextLabel("LeftLegLabel","Left Leg",UDim2.new(0.5,-16,0,-25),leftLegButton) - local rightLegButton = makeStyledButton("RightLegMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-64,0.5,-25),MeshFrame,Enum.ButtonStyle.RobloxButton) - makeTextLabel("RightLegLabel","Right Leg",UDim2.new(0.5,-16,0,-25),rightLegButton) - local rightArmButton = makeStyledButton("RightArmMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-96,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton) - makeTextLabel("RightArmLabel","Right Arm",UDim2.new(0.5,-16,0,-25),rightArmButton) - local leftArmButton = makeStyledButton("LeftArmMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,32,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton) - makeTextLabel("LeftArmLabel","Left Arm",UDim2.new(0.5,-16,0,-25),leftArmButton) - - local TShirtFrame = makeCharFrame("T-ShirtsFrame",CharacterPane) - game:GetService("ContentProvider"):Preload("http://www.morblox.us/asset/?id=75460642") - makeZone("TShirtZone","http://www.morblox.us/asset/?id=75460642",UDim2.new(0,121,0,154),UDim2.new(0.5,-60,0.5,-100),TShirtFrame) - makeStyledButton("TShirtButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-64),TShirtFrame) - - - local ShirtFrame = makeCharFrame("ShirtsFrame", CharacterPane) - makeZone("ShirtZone","http://www.morblox.us/asset/?id=75460642",UDim2.new(0,121,0,154),UDim2.new(0.5,-60,0.5,-100),ShirtFrame) - makeStyledButton("ShirtButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-64),ShirtFrame) - - - local ColorFrame = makeCharFrame("ColorFrame", CharacterPane) - game:GetService("ContentProvider"):Preload("http://www.morblox.us/asset/?id=76049888") - local ColorZone = makeZone("ColorZone","http://www.morblox.us/asset/?id=76049888", UDim2.new(0,120,0,150),UDim2.new(0.5,-60,0.5,-100),ColorFrame) - makeStyledButton("Head",UDim2.new(0.26,0,0.19,0),UDim2.new(0.37,0,0.02,0),ColorZone).AutoButtonColor = false - makeStyledButton("LeftArm",UDim2.new(0.19,0,0.36,0),UDim2.new(0.78,0,0.26,0),ColorZone).AutoButtonColor = false - makeStyledButton("RightArm",UDim2.new(0.19,0,0.36,0),UDim2.new(0.025,0,0.26,0),ColorZone).AutoButtonColor = false - makeStyledButton("Torso",UDim2.new(0.43,0,0.36,0),UDim2.new(0.28,0,0.26,0),ColorZone).AutoButtonColor = false - makeStyledButton("RightLeg",UDim2.new(0.19,0,0.31,0),UDim2.new(0.275,0,0.67,0),ColorZone).AutoButtonColor = false - makeStyledButton("LeftLeg",UDim2.new(0.19,0,0.31,0),UDim2.new(0.525,0,0.67,0),ColorZone).AutoButtonColor = false - - -- Character Panel label (shows what category we are currently browsing) - local CategoryLabel = Instance.new("TextLabel") - CategoryLabel.RobloxLocked = true - CategoryLabel.Name = "CategoryLabel" - CategoryLabel.BackgroundTransparency = 1 - CategoryLabel.Font = Enum.Font.ArialBold - CategoryLabel.FontSize = Enum.FontSize.Size18 - CategoryLabel.Position = UDim2.new(0,0,0,-7) - CategoryLabel.Size = UDim2.new(1,0,0,20) - CategoryLabel.TextXAlignment = Enum.TextXAlignment.Center - CategoryLabel.Text = "All" - CategoryLabel.TextColor3 = Color3.new(1,1,1) - CategoryLabel.Parent = CharacterPane - - --Save Button - local SaveButton = Instance.new("TextButton") - SaveButton.RobloxLocked = true - SaveButton.Name = "SaveButton" - SaveButton.Size = UDim2.new(0.6,0,0,50) - SaveButton.Position = UDim2.new(0.2,0,1,-50) - SaveButton.Style = Enum.ButtonStyle.RobloxButton - SaveButton.Selected = false - SaveButton.Font = Enum.Font.ArialBold - SaveButton.FontSize = Enum.FontSize.Size18 - SaveButton.Text = "Save" - SaveButton.TextColor3 = Color3.new(1,1,1) - SaveButton.Parent = CharacterPane - --- no need for this to stick around - -script:Destroy() \ No newline at end of file +%12% +-- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search) +print("mamanger") +if game.CoreGui.Version < 7 then return end -- peace out if we aren't using the right client +print("made it past gui version check") + +-- basic functions +local function waitForChild(instance, name) + while not instance:FindFirstChild(name) do + instance.ChildAdded:wait() + end + return instance:FindFirstChild(name) +end +local function waitForProperty(instance, property) + while not instance[property] do + instance.Changed:wait() + end +end + +-- don't do anything if we are in an empty game +waitForChild(game,"Players") +if #game.Players:GetChildren() < 1 then + game.Players.ChildAdded:wait() +end +-- make sure everything is loaded in before we do anything +-- get our local player +waitForProperty(game.Players,"LocalPlayer") +local player = game.Players.LocalPlayer + + + +------------------------ Locals ------------------------------ +local backpack = script.Parent +waitForChild(backpack,"Gear") + +local screen = script.Parent.Parent +assert(screen:IsA("ScreenGui")) + +waitForChild(backpack, "Tabs") +waitForChild(backpack.Tabs, "CloseButton") +local closeButton = backpack.Tabs.CloseButton + +waitForChild(backpack.Tabs, "InventoryButton") +local inventoryButton = backpack.Tabs.InventoryButton +if game.CoreGui.Version >= 8 then + waitForChild(backpack.Tabs, "WardrobeButton") + local wardrobeButton = backpack.Tabs.WardrobeButton +end +waitForChild(backpack.Parent,"ControlFrame") +local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton") +local currentTab = "gear" + +local searchFrame = waitForChild(backpack,"SearchFrame") +waitForChild(backpack.SearchFrame,"SearchBoxFrame") +local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox") +local searchButton = waitForChild(backpack.SearchFrame,"SearchButton") +local resetButton = waitForChild(backpack.SearchFrame,"ResetButton") + +local canToggle = true +local readyForNextEvent = true +local backpackIsOpen = false +local active = true + +local humanoidDiedCon = nil + +local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack + +local searchDefaultText = "Search..." +local tilde = "~" +local backquote = "`" + +------------------------ End Locals --------------------------- + + +---------------------------------------- Public Event Setup ---------------------------------------- + +function createPublicEvent(eventName) + assert(eventName, "eventName is nil") + assert(tostring(eventName),"eventName is not a string") + + local newEvent = Instance.new("BindableEvent") + newEvent.Name = tostring(eventName) + newEvent.Parent = script + + return newEvent +end + +function createPublicFunction(funcName, invokeFunc) + assert(funcName, "funcName is nil") + assert(tostring(funcName), "funcName is not a string") + assert(invokeFunc, "invokeFunc is nil") + assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'") + + local newFunction = Instance.new("BindableFunction") + newFunction.Name = tostring(funcName) + newFunction.OnInvoke = invokeFunc + newFunction.Parent = script + + return newFunction +end + +-- Events +local resizeEvent = createPublicEvent("ResizeEvent") +local backpackOpenEvent = createPublicEvent("BackpackOpenEvent") +local backpackCloseEvent = createPublicEvent("BackpackCloseEvent") +local tabClickedEvent = createPublicEvent("TabClickedEvent") +local searchRequestedEvent = createPublicEvent("SearchRequestedEvent") +---------------------------------------- End Public Event Setup ---------------------------------------- + + + +--------------------------- Internal Functions ---------------------------------------- + +function deactivateBackpack() + backpack.Visible = false + active = false +end + +function activateBackpack() + initHumanoidDiedConnections() + active = true + backpack.Visible = backpackIsOpen +end + +function initHumanoidDiedConnections() + if humanoidDiedCon then + humanoidDiedCon:disconnect() + end + waitForProperty(game.Players.LocalPlayer,"Character") + waitForChild(game.Players.LocalPlayer.Character,"Humanoid") + humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack) +end + +local hideBackpack = function() + backpackIsOpen = false + readyForNextEvent = false + backpackButton.Selected = false + resetSearch() + backpackCloseEvent:Fire(currentTab) + backpack.Tabs.Visible = false + searchFrame.Visible = false + backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true, + function() + game.GuiService:RemoveCenterDialog(backpack) + backpack.Visible = false + backpackButton.Selected = false + end) + delay(guiTweenSpeed,function() + game.GuiService:RemoveCenterDialog(backpack) + backpack.Visible = false + backpackButton.Selected = false + canToggle = true + end) +end + +function showBackpack() + game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog, + function() + backpack.Visible = true + backpackButton.Selected = true + end, + function() + backpack.Visible = false + backpackButton.Selected = false + end) + backpack.Visible = true + backpackButton.Selected = true + backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.76, 0),UDim2.new(0.225, 0, 0.09, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true) + delay(guiTweenSpeed,function() + backpack.Tabs.Visible = true + searchFrame.Visible = true + backpackOpenEvent:Fire(currentTab) + canToggle = true + end) +end + +function toggleBackpack() + if not game.Players.LocalPlayer then return end + if not game.Players.LocalPlayer["Character"] then return end + + if not canToggle then return end + if not readyForNextEvent then return end + readyForNextEvent = false + canToggle = false + + backpackIsOpen = not backpackIsOpen + + if backpackIsOpen then + showBackpack() + else + backpackButton.Selected = false + hideBackpack() + end +end + +function closeBackpack() + if backpackIsOpen then + toggleBackpack() + end +end + +function setSelected(tab) + assert(tab) + assert(tab:IsA("TextButton")) + + tab.BackgroundColor3 = Color3.new(1,1,1) + tab.TextColor3 = Color3.new(0,0,0) + tab.Selected = true + tab.ZIndex = 3 +end + +function setUnselected(tab) + assert(tab) + assert(tab:IsA("TextButton")) + + tab.BackgroundColor3 = Color3.new(0,0,0) + tab.TextColor3 = Color3.new(1,1,1) + tab.Selected = false + tab.ZIndex = 1 +end + +function updateTabGui(selectedTab) + assert(selectedTab) + + if selectedTab == "gear" then + setSelected(inventoryButton) + setUnselected(wardrobeButton) + elseif selectedTab == "wardrobe" then + setSelected(wardrobeButton) + setUnselected(inventoryButton) + end +end + +function mouseLeaveTab(button) + assert(button) + assert(button:IsA("TextButton")) + + if button.Selected then return end + + button.BackgroundColor3 = Color3.new(0,0,0) +end + +function mouseOverTab(button) + assert(button) + assert(button:IsA("TextButton")) + + if button.Selected then return end + + button.BackgroundColor3 = Color3.new(39/255,39/255,39/255) +end + +function newTabClicked(tabName) + assert(tabName) + tabName = string.lower(tabName) + currentTab = tabName + + updateTabGui(tabName) + tabClickedEvent:Fire(tabName) + resetSearch() +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function splitByWhitespace(text) + if type(text) ~= "string" then return nil end + + local terms = {} + for token in string.gmatch(text, "[^%s]+") do + if string.len(token) > 0 then + table.insert(terms,token) + end + end + return terms +end + +function resetSearchBoxGui() + resetButton.Visible = false + searchBox.Text = searchDefaultText +end + +function doSearch() + local searchText = searchBox.Text + if searchText == "" then + resetSearch() + return + end + searchText = trim(searchText) + resetButton.Visible = true + termTable = splitByWhitespace(searchText) + searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible +end + +function resetSearch() + resetSearchBoxGui() + searchRequestedEvent:Fire() +end + +local backpackReady = function() + readyForNextEvent = true +end + +--------------------------- End Internal Functions ------------------------------------- + + +------------------------------ Public Functions Setup ------------------------------------- +createPublicFunction("CloseBackpack", hideBackpack) +createPublicFunction("BackpackReady", backpackReady) +------------------------------ End Public Functions Setup --------------------------------- + + +------------------------ Connections/Script Main ------------------------------------------- + +inventoryButton.MouseButton1Click:connect(function() newTabClicked("gear") end) +inventoryButton.MouseEnter:connect(function() mouseOverTab(inventoryButton) end) +inventoryButton.MouseLeave:connect(function() mouseLeaveTab(inventoryButton) end) + +if game.CoreGui.Version >= 8 then + wardrobeButton.MouseButton1Click:connect(function() newTabClicked("wardrobe") end) + wardrobeButton.MouseEnter:connect(function() mouseOverTab(wardrobeButton) end) + wardrobeButton.MouseLeave:connect(function() mouseLeaveTab(wardrobeButton) end) +end + +closeButton.MouseButton1Click:connect(closeBackpack) + +screen.Changed:connect(function(prop) + if prop == "AbsoluteSize" then + resizeEvent:Fire(screen.AbsoluteSize) + end +end) + +-- GuiService key setup +game:GetService("GuiService"):AddKey(tilde) +game:GetService("GuiService"):AddKey(backquote) +game:GetService("GuiService").KeyPressed:connect(function(key) + if not active then return end + if key == tilde or key == backquote then + toggleBackpack() + end +end) +backpackButton.MouseButton1Click:connect(function() + if not active then return end + toggleBackpack() +end) + +if game.Players.LocalPlayer["Character"] then + activateBackpack() +end +game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack) + +-- search functions +searchBox.FocusLost:connect(function(enterPressed) + if enterPressed or searchBox.Text ~= "" then + doSearch() + elseif searchBox.Text == "" then + resetSearch() + end +end) +searchButton.MouseButton1Click:connect(doSearch) +resetButton.MouseButton1Click:connect(resetSearch) + +backpackButton.Visible = true diff --git a/public/asset/13 b/public/asset/13 index f54db0e..5d2f3e2 100644 --- a/public/asset/13 +++ b/public/asset/13 @@ -1,416 +1,843 @@ -%13% --- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search) -if game.CoreGui.Version < 7 then return end -- peace out if we aren't using the right client - --- basic functions -local function waitForChild(instance, name) - while not instance:FindFirstChild(name) do - instance.ChildAdded:wait() - end - return instance:FindFirstChild(name) -end -local function waitForProperty(instance, property) - while not instance[property] do - instance.Changed:wait() - end -end - --- don't do anything if we are in an empty game -waitForChild(game,"Players") -if #game.Players:GetChildren() < 1 then - game.Players.ChildAdded:wait() -end --- make sure everything is loaded in before we do anything --- get our local player -waitForProperty(game.Players,"LocalPlayer") -local player = game.Players.LocalPlayer - - - ------------------------- Locals ------------------------------ -local backpack = script.Parent -waitForChild(backpack,"Gear") - -local screen = script.Parent.Parent -assert(screen:IsA("ScreenGui")) - -waitForChild(backpack, "Tabs") -waitForChild(backpack.Tabs, "CloseButton") -local closeButton = backpack.Tabs.CloseButton - -waitForChild(backpack.Tabs, "InventoryButton") -local inventoryButton = backpack.Tabs.InventoryButton -if game.CoreGui.Version >= 8 then - waitForChild(backpack.Tabs, "WardrobeButton") - local wardrobeButton = backpack.Tabs.WardrobeButton -end -waitForChild(backpack.Parent,"ControlFrame") -local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton") -local currentTab = "gear" - -local searchFrame = waitForChild(backpack,"SearchFrame") -waitForChild(backpack.SearchFrame,"SearchBoxFrame") -local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox") -local searchButton = waitForChild(backpack.SearchFrame,"SearchButton") -local resetButton = waitForChild(backpack.SearchFrame,"ResetButton") - -local robloxGui = waitForChild(Game.CoreGui, 'RobloxGui') -local currentLoadout = waitForChild(robloxGui, 'CurrentLoadout') -local loadoutBackground = waitForChild(currentLoadout, 'Background') - -local canToggle = true -local readyForNextEvent = true -local backpackIsOpen = false -local active = true - -local humanoidDiedCon = nil - -local backpackButtonPos - -local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack - -local searchDefaultText = "Search..." -local tilde = "~" -local backquote = "`" - -local backpackSize = UDim2.new(0, 600, 0, 400) - -if robloxGui.AbsoluteSize.Y <= 320 then - backpackSize = UDim2.new(0, 200, 0, 140) -end - ------------------------- End Locals --------------------------- - - ----------------------------------------- Public Event Setup ---------------------------------------- - -function createPublicEvent(eventName) - assert(eventName, "eventName is nil") - assert(tostring(eventName),"eventName is not a string") - - local newEvent = Instance.new("BindableEvent") - newEvent.Name = tostring(eventName) - newEvent.Parent = script - - return newEvent -end - -function createPublicFunction(funcName, invokeFunc) - assert(funcName, "funcName is nil") - assert(tostring(funcName), "funcName is not a string") - assert(invokeFunc, "invokeFunc is nil") - assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'") - - local newFunction = Instance.new("BindableFunction") - newFunction.Name = tostring(funcName) - newFunction.OnInvoke = invokeFunc - newFunction.Parent = script - - return newFunction -end - --- Events -local resizeEvent = createPublicEvent("ResizeEvent") -local backpackOpenEvent = createPublicEvent("BackpackOpenEvent") -local backpackCloseEvent = createPublicEvent("BackpackCloseEvent") -local tabClickedEvent = createPublicEvent("TabClickedEvent") -local searchRequestedEvent = createPublicEvent("SearchRequestedEvent") ----------------------------------------- End Public Event Setup ---------------------------------------- - - - ---------------------------- Internal Functions ---------------------------------------- - -function deactivateBackpack() - backpack.Visible = false - active = false -end - -function activateBackpack() - initHumanoidDiedConnections() - active = true - backpack.Visible = backpackIsOpen - if backpackIsOpen then - toggleBackpack() - end -end - -function initHumanoidDiedConnections() - if humanoidDiedCon then - humanoidDiedCon:disconnect() - end - waitForProperty(game.Players.LocalPlayer,"Character") - waitForChild(game.Players.LocalPlayer.Character,"Humanoid") - humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack) -end - -local hideBackpack = function() - backpackIsOpen = false - readyForNextEvent = false - backpackButton.Selected = false - resetSearch() - backpackCloseEvent:Fire(currentTab) - backpack.Tabs.Visible = false - searchFrame.Visible = false - backpack:TweenSizeAndPosition(UDim2.new(0, backpackSize.X.Offset,0, 0), UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -85), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true, - function() - game.GuiService:RemoveCenterDialog(backpack) - backpack.Visible = false - backpackButton.Selected = false - end) - delay(guiTweenSpeed,function() - game.GuiService:RemoveCenterDialog(backpack) - backpack.Visible = false - backpackButton.Selected = false - readyForNextEvent = true - canToggle = true - end) -end - -function showBackpack() - game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog, - function() - backpack.Visible = true - backpackButton.Selected = true - end, - function() - backpack.Visible = false - backpackButton.Selected = false - end) - backpack.Visible = true - backpackButton.Selected = true - backpack:TweenSizeAndPosition(backpackSize, UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -backpackSize.Y.Offset - 88), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true) - delay(guiTweenSpeed,function() - backpack.Tabs.Visible = false - searchFrame.Visible = true - backpackOpenEvent:Fire(currentTab) - canToggle = true - readyForNextEvent = true - backpackButton.Image = 'rbxasset://Textures/IPadInGameGUIToolbarBkpkTabTopV4.png' - backpackButton.Position = UDim2.new(0.5, -60, 1, -backpackSize.Y.Offset - 103) - end) -end - -function toggleBackpack() - if not game.Players.LocalPlayer then return end - if not game.Players.LocalPlayer["Character"] then return end - if not canToggle then return end - if not readyForNextEvent then return end - readyForNextEvent = false - canToggle = false - - backpackIsOpen = not backpackIsOpen - - if backpackIsOpen then - loadoutBackground.Image = 'rbxasset://Textures/IPadInGameGUIToolBarBkgd.png' - loadoutBackground.Position = UDim2.new(-0.03, 0, -0.17, 0) - loadoutBackground.Size = UDim2.new(1.05, 0, 1.25, 0) - loadoutBackground.ZIndex = 2.0 - loadoutBackground.Visible = true - --backpackButton.Position = UDim2.new(0.5, -60, 1, -503) - showBackpack() - else - backpackButton.Position = UDim2.new(0.5, -60, 1, -44) - loadoutBackground.Visible = false - backpackButton.Selected = false - backpackButton.Image = "rbxasset://Textures/IPadInGameGUIToolbarBkpkTabTopV3.png" - loadoutBackground.Image = 'rbxasset://Textures/IPadInGameGUIToolbar.png' - loadoutBackground.Position = UDim2.new(-0.1, 0, -0.1, 0) - loadoutBackground.Size = UDim2.new(1.2, 0, 1.2, 0) - hideBackpack() - - - local clChildren = currentLoadout:GetChildren() - for i = 1, #clChildren do - if clChildren[i] and clChildren[i]:IsA('Frame') then - local frame = clChildren[i] - if #frame:GetChildren() > 0 then - backpackButton.Position = UDim2.new(0.5, -60, 1, -108) - backpackButton.Visible = true - loadoutBackground.Visible = true - if frame:GetChildren()[1]:IsA('ImageButton') then - local imgButton = frame:GetChildren()[1] - imgButton.Active = true - imgButton.Draggable = false - end - end - end - end - - end -end - -function closeBackpack() - if backpackIsOpen then - toggleBackpack() - end -end - -function setSelected(tab) - assert(tab) - assert(tab:IsA("TextButton")) - - tab.BackgroundColor3 = Color3.new(1,1,1) - tab.TextColor3 = Color3.new(0,0,0) - tab.Selected = true - tab.ZIndex = 3 -end - -function setUnselected(tab) - assert(tab) - assert(tab:IsA("TextButton")) - - tab.BackgroundColor3 = Color3.new(0,0,0) - tab.TextColor3 = Color3.new(1,1,1) - tab.Selected = false - tab.ZIndex = 1 -end - -function updateTabGui(selectedTab) - assert(selectedTab) - - if selectedTab == "gear" then - setSelected(inventoryButton) - setUnselected(wardrobeButton) - elseif selectedTab == "wardrobe" then - setSelected(wardrobeButton) - setUnselected(inventoryButton) - end -end - -function mouseLeaveTab(button) - assert(button) - assert(button:IsA("TextButton")) - - if button.Selected then return end - - button.BackgroundColor3 = Color3.new(0,0,0) -end - -function mouseOverTab(button) - assert(button) - assert(button:IsA("TextButton")) - - if button.Selected then return end - - button.BackgroundColor3 = Color3.new(39/255,39/255,39/255) -end - -function newTabClicked(tabName) - assert(tabName) - tabName = string.lower(tabName) - currentTab = tabName - - updateTabGui(tabName) - tabClickedEvent:Fire(tabName) - resetSearch() -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function splitByWhitespace(text) - if type(text) ~= "string" then return nil end - - local terms = {} - for token in string.gmatch(text, "[^%s]+") do - if string.len(token) > 0 then - table.insert(terms,token) - end - end - return terms -end - -function resetSearchBoxGui() - resetButton.Visible = false - searchBox.Text = searchDefaultText -end - -function doSearch() - local searchText = searchBox.Text - if searchText == "" then - resetSearch() - return - end - searchText = trim(searchText) - resetButton.Visible = true - termTable = splitByWhitespace(searchText) - searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible -end - -function resetSearch() - resetSearchBoxGui() - searchRequestedEvent:Fire() -end - -local backpackReady = function() - readyForNextEvent = true -end - ---------------------------- End Internal Functions ------------------------------------- - - ------------------------------- Public Functions Setup ------------------------------------- -createPublicFunction("CloseBackpack", hideBackpack) -createPublicFunction("BackpackReady", backpackReady) ------------------------------- End Public Functions Setup --------------------------------- - - ------------------------- Connections/Script Main ------------------------------------------- - -inventoryButton.MouseButton1Click:connect(function() newTabClicked("gear") end) -inventoryButton.MouseEnter:connect(function() mouseOverTab(inventoryButton) end) -inventoryButton.MouseLeave:connect(function() mouseLeaveTab(inventoryButton) end) - -if game.CoreGui.Version >= 8 then - wardrobeButton.MouseButton1Click:connect(function() newTabClicked("wardrobe") end) - wardrobeButton.MouseEnter:connect(function() mouseOverTab(wardrobeButton) end) - wardrobeButton.MouseLeave:connect(function() mouseLeaveTab(wardrobeButton) end) -end - -closeButton.MouseButton1Click:connect(closeBackpack) - -screen.Changed:connect(function(prop) - if prop == "AbsoluteSize" then - resizeEvent:Fire(screen.AbsoluteSize) - end -end) - --- GuiService key setup -game:GetService("GuiService"):AddKey(tilde) -game:GetService("GuiService"):AddKey(backquote) -game:GetService("GuiService").KeyPressed:connect(function(key) - if not active then return end - if key == tilde or key == backquote then - toggleBackpack() - end -end) -backpackButton.MouseButton1Click:connect(function() - if not active then return end - toggleBackpack() -end) - -if game.Players.LocalPlayer["Character"] then - activateBackpack() -end - -game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack) - --- search functions -searchBox.FocusLost:connect(function(enterPressed) - if enterPressed or searchBox.Text ~= "" then - doSearch() - elseif searchBox.Text == "" then - resetSearch() - end -end) -searchButton.MouseButton1Click:connect(doSearch) -resetButton.MouseButton1Click:connect(resetSearch) - -if searchFrame and robloxGui.AbsoluteSize.Y <= 320 then - searchFrame.RobloxLocked = false - searchFrame:Destroy() -end - ---backpackButton.Visible = true \ No newline at end of file +%13% +-- A couple of necessary functions +local function waitForChild(instance, name) + assert(instance) + assert(name) + while not instance:FindFirstChild(name) do + instance.ChildAdded:wait() + end + return instance:FindFirstChild(name) +end +local function waitForProperty(instance, property) + assert(instance) + assert(property) + while not instance[property] do + instance.Changed:wait() + end +end + +waitForChild(game,"Players") +waitForProperty(game.Players,"LocalPlayer") +local player = game.Players.LocalPlayer + +local RbxGui, msg = LoadLibrary("RbxGui") +if not RbxGui then print("could not find RbxGui!") return end + +--- Begin Locals +local StaticTabName = "gear" + +local backpack = script.Parent +local screen = script.Parent.Parent + +local backpackItems = {} +local buttons = {} + +local debounce = false +local browsingMenu = false + +local mouseEnterCons = {} +local mouseClickCons = {} + +local characterChildAddedCon = nil +local characterChildRemovedCon = nil +local backpackAddCon = nil + +local playerBackpack = waitForChild(player,"Backpack") + +waitForChild(backpack,"Tabs") + +waitForChild(backpack,"Gear") +local gearPreview = waitForChild(backpack.Gear,"GearPreview") + +local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea") + +local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout") + +local grid = waitForChild(backpack.Gear,"GearGrid") +local gearButton = waitForChild(grid,"GearButton") + +local swapSlot = waitForChild(script.Parent,"SwapSlot") + +local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager") +local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent") +local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent") +local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent") +local resizeEvent = waitForChild(backpackManager,"ResizeEvent") +local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent") +local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady") + +-- creating scroll bar early as to make sure items get placed correctly +local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid") + +scrollFrame.Position = UDim2.new(0,0,0,30) +scrollFrame.Size = UDim2.new(1,0,1,-30) +scrollFrame.Parent = backpack.Gear.GearGrid + +local scrollBar = Instance.new("Frame") +scrollBar.Name = "ScrollBar" +scrollBar.BackgroundTransparency = 0.9 +scrollBar.BackgroundColor3 = Color3.new(1,1,1) +scrollBar.BorderSizePixel = 0 +scrollBar.Size = UDim2.new(0, 17, 1, -36) +scrollBar.Position = UDim2.new(0,0,0,18) +scrollBar.Parent = scroller + +scrollDown.Position = UDim2.new(0,0,1,-17) + +scrollUp.Parent = scroller +scrollDown.Parent = scroller + +local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame() + +scrollFrameLoadout.Position = UDim2.new(0,0,0,0) +scrollFrameLoadout.Size = UDim2.new(1,0,1,0) +scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList + +local LoadoutButton = Instance.new("TextButton") +LoadoutButton.RobloxLocked = true +LoadoutButton.Name = "LoadoutButton" +LoadoutButton.Font = Enum.Font.ArialBold +LoadoutButton.FontSize = Enum.FontSize.Size14 +LoadoutButton.Position = UDim2.new(0,0,0,0) +LoadoutButton.Size = UDim2.new(1,0,0,32) +LoadoutButton.Style = Enum.ButtonStyle.RobloxButton +LoadoutButton.Text = "Loadout #1" +LoadoutButton.TextColor3 = Color3.new(1,1,1) +LoadoutButton.Parent = scrollFrameLoadout + +local LoadoutButtonTwo = LoadoutButton:clone() +LoadoutButtonTwo.Text = "Loadout #2" +LoadoutButtonTwo.Parent = scrollFrameLoadout + +local LoadoutButtonThree = LoadoutButton:clone() +LoadoutButtonThree.Text = "Loadout #3" +LoadoutButtonThree.Parent = scrollFrameLoadout + +local LoadoutButtonFour = LoadoutButton:clone() +LoadoutButtonFour.Text = "Loadout #4" +LoadoutButtonFour.Parent = scrollFrameLoadout + +local scrollBarLoadout = Instance.new("Frame") +scrollBarLoadout.Name = "ScrollBarLoadout" +scrollBarLoadout.BackgroundTransparency = 0.9 +scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1) +scrollBarLoadout.BorderSizePixel = 0 +scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36) +scrollBarLoadout.Position = UDim2.new(0,0,0,18) +scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea + +scrollDownLoadout.Position = UDim2.new(0,0,1,-17) + +scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea +scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea + + +-- Begin Functions +function removeFromMap(map,object) + for i = 1, #map do + if map[i] == object then + table.remove(map,i) + break + end + end +end + +function robloxLock(instance) + instance.RobloxLocked = true + children = instance:GetChildren() + if children then + for i, child in ipairs(children) do + robloxLock(child) + end + end +end + +function resize() + local size = 0 + if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then + size = gearPreview.AbsoluteSize.X * 0.75 + else + size = gearPreview.AbsoluteSize.Y * 0.75 + end + + waitForChild(gearPreview,"GearImage") + gearPreview.GearImage.Size = UDim2.new(0,size,0,size) + gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size) + + resizeGrid() +end + +function addToGrid(child) + if not child:IsA("Tool") then + if not child:IsA("HopperBin") then + return + end + end + if child:FindFirstChild("RobloxBuildTool") then return end + + for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered + if v == child then return end + end + + table.insert(backpackItems,child) + + local changeCon = child.Changed:connect(function(prop) + if prop == "Name" then + if buttons[child] then + if buttons[child].Image == "" then + buttons[child].GearText.Text = child.Name + end + end + end + end) + local ancestryCon = nil + ancestryCon = child.AncestryChanged:connect(function(theChild,theParent) + local thisObject = nil + for k,v in pairs(backpackItems) do + if v == child then + thisObject = v + break + end + end + + waitForProperty(player,"Character") + waitForChild(player,"Backpack") + if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then + if ancestryCon then ancestryCon:disconnect() end + if changeCon then changeCon:disconnect() end + + for k,v in pairs(backpackItems) do + if v == thisObject then + if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end + if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end + buttons[v].Parent = nil + buttons[v] = nil + break + end + end + + removeFromMap(backpackItems,thisObject) + + resizeGrid() + else + resizeGrid() + end + updateGridActive() + end) + resizeGrid() +end + +function buttonClick(button) + if button:FindFirstChild("UnequipContextMenu") and not button.Active then + button.UnequipContextMenu.Visible = true + browsingMenu = true + end +end + +function previewGear(button) + if not browsingMenu then + gearPreview.GearImage.Image = button.Image + gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name + end +end + +function findEmptySlot() + local smallestNum = nil + local loadout = currentLoadout:GetChildren() + for i = 1, #loadout do + if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then + local frameNum = tonumber(string.sub(loadout[i].Name,5)) + if frameNum == 0 then frameNum = 10 end + if not smallestNum or (smallestNum > frameNum) then + smallestNum = frameNum + end + end + end + if smallestNum == 10 then smallestNum = 0 end + return smallestNum +end + +function checkForSwap(button,x,y) + local loadoutChildren = currentLoadout:GetChildren() + for i = 1, #loadoutChildren do + if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then + if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then + if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then + local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) + swapGearSlot(slot,button) + return true + end + end + end + end + return false +end + +function resizeGrid() + for k,v in pairs(backpackItems) do + if not v:FindFirstChild("RobloxBuildTool") then + if not buttons[v] then + local buttonClone = gearButton:clone() + buttonClone.Parent = grid.ScrollingFrame + buttonClone.Visible = true + buttonClone.Image = v.TextureId + if buttonClone.Image == "" then + buttonClone.GearText.Text = v.Name + end + + buttonClone.GearReference.Value = v + buttonClone.Draggable = true + buttons[v] = buttonClone + + local unequipMenu = getGearContextMenu() + + unequipMenu.Visible = false + unequipMenu.Parent = buttonClone + + local beginPos = nil + buttonClone.DragBegin:connect(function(value) + buttonClone.ZIndex = 9 + beginPos = value + end) + buttonClone.DragStopped:connect(function(x,y) + buttonClone.ZIndex = 1 + if beginPos ~= buttonClone.Position then + if not checkForSwap(buttonClone,x,y) then + buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true) + buttonClone.Draggable = false + delay(0.5,function() + buttonClone.Draggable = true + end) + else + buttonClone.Position = beginPos + end + end + end) + local clickTime = tick() + mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end) + mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() + local newClickTime = tick() + if buttonClone.Active and (newClickTime - clickTime) < 0.5 then + local slot = findEmptySlot() + if slot then + buttonClone.ZIndex = 1 + swapGearSlot(slot,buttonClone) + end + else + buttonClick(buttonClone) + end + clickTime = newClickTime + end) + end + end + end + recalculateScroll() +end + +function showPartialGrid(subset) + for k,v in pairs(buttons) do + v.Parent = nil + end + if subset then + for k,v in pairs(subset) do + v.Parent = grid.ScrollingFrame + end + end + recalculateScroll() +end + +function showEntireGrid() + for k,v in pairs(buttons) do + v.Parent = grid.ScrollingFrame + end + recalculateScroll() +end + +function inLoadout(gear) + local children = currentLoadout:GetChildren() + for i = 1, #children do + if children[i]:IsA("Frame") then + local button = children[i]:GetChildren() + if #button > 0 then + if button[1].GearReference.Value and button[1].GearReference.Value == gear then + return true + end + end + end + end + return false +end + +function updateGridActive() + for k,v in pairs(backpackItems) do + if buttons[v] then + local gear = nil + local gearRef = buttons[v]:FindFirstChild("GearReference") + + if gearRef then gear = gearRef.Value end + + if not gear then + buttons[v].Active = false + elseif inLoadout(gear) then + buttons[v].Active = false + else + buttons[v].Active = true + end + end + end +end + +function centerGear(loadoutChildren) + local gearButtons = {} + local lastSlotAdd = nil + for i = 1, #loadoutChildren do + if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then + if loadoutChildren[i].Name == "Slot0" then + lastSlotAdd = loadoutChildren[i] + else + table.insert(gearButtons, loadoutChildren[i]) + end + end + end + if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end + + local startPos = ( 1 - (#gearButtons * 0.1) ) / 2 + for i = 1, #gearButtons do + gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) + end +end + +function tabClickHandler(tabName) + if tabName == StaticTabName then + backpackOpenHandler(tabName) + else + backpackCloseHandler(tabName) + end +end + +function backpackOpenHandler(currentTab) + if currentTab and currentTab ~= StaticTabName then + backpack.Gear.Visible = false + return + end + + backpack.Gear.Visible = true + updateGridActive() + + resizeGrid() + resize() + tellBackpackReadyFunc:Invoke() +end + +function backpackCloseHandler(currentTab) + if currentTab and currentTab ~= StaticTabName then + backpack.Gear.Visible = false + return + end + + backpack.Gear.Visible = false + + resizeGrid() + resize() + tellBackpackReadyFunc:Invoke() +end + +function loadoutCheck(child, selectState) + if not child:IsA("ImageButton") then return end + for k,v in pairs(backpackItems) do + if buttons[v] then + if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then + if buttons[v].GearReference.Value == child.GearReference.Value then + buttons[v].Active = selectState + break + end + end + end + end +end + +function clearPreview() + gearPreview.GearImage.Image = "" + gearPreview.GearStats.GearName.Text = "" +end + +function removeAllEquippedGear(physGear) + local stuff = player.Character:GetChildren() + for i = 1, #stuff do + if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then + stuff[i].Parent = playerBackpack + end + end +end + +function equipGear(physGear) + removeAllEquippedGear(physGear) + physGear.Parent = player.Character + updateGridActive() +end + +function unequipGear(physGear) + physGear.Parent = playerBackpack + updateGridActive() +end + +function highlight(button) + button.TextColor3 = Color3.new(0,0,0) + button.BackgroundColor3 = Color3.new(0.8,0.8,0.8) +end +function clearHighlight(button) + button.TextColor3 = Color3.new(1,1,1) + button.BackgroundColor3 = Color3.new(0,0,0) +end + +function swapGearSlot(slot,gearButton) + if not swapSlot.Value then -- signal loadout to swap a gear out + swapSlot.Slot.Value = slot + swapSlot.GearButton.Value = gearButton + swapSlot.Value = true + updateGridActive() + end +end + + +local UnequipGearMenuClick = function(element, menu) + if type(element.Action) ~= "number" then return end + local num = element.Action + if num == 1 then -- remove from loadout + unequipGear(menu.Parent.GearReference.Value) + local inventoryButton = menu.Parent + local gearToUnequip = inventoryButton.GearReference.Value + local loadoutChildren = currentLoadout:GetChildren() + local slot = -1 + for i = 1, #loadoutChildren do + if loadoutChildren[i]:IsA("Frame") then + local button = loadoutChildren[i]:GetChildren() + if button[1] and button[1].GearReference.Value == gearToUnequip then + slot = button[1].SlotNumber.Text + break + end + end + end + swapGearSlot(slot,nil) + end +end + +function setupCharacterConnections() + + if backpackAddCon then backpackAddCon:disconnect() end + backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) + + -- make sure we get all the children + local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren() + for i = 1, #backpackChildren do + addToGrid(backpackChildren[i]) + end + + if characterChildAddedCon then characterChildAddedCon:disconnect() end + characterChildAddedCon = + game.Players.LocalPlayer.Character.ChildAdded:connect(function(child) + addToGrid(child) + updateGridActive() + end) + + if characterChildRemovedCon then characterChildRemovedCon:disconnect() end + characterChildRemovedCon = + game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child) + updateGridActive() + end) + + wait() + centerGear(currentLoadout:GetChildren()) +end + +function removeCharacterConnections() + if characterChildAddedCon then characterChildAddedCon:disconnect() end + if characterChildRemovedCon then characterChildRemovedCon:disconnect() end + if backpackAddCon then backpackAddCon:disconnect() end +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function filterGear(terms) + local filteredGear = {} + for k,v in pairs(backpackItems) do + if buttons[v] then + local gearString = string.lower(buttons[v].GearReference.Value.Name) + gearString = trim(gearString) + for i = 1, #terms do + if string.match(gearString,terms[i]) then + table.insert(filteredGear,buttons[v]) + break + end + end + end + end + + return filteredGear +end +function splitByWhitespace(text) + if type(text) ~= "string" then return nil end + + local terms = {} + for token in string.gmatch(text, "[^%s]+") do + if string.len(token) > 0 then + table.insert(terms,token) + end + end + return terms +end +function showSearchGear(searchTerms) + if not backpack.Gear.Visible then return end -- currently not active tab + + local searchTermTable = splitByWhitespace(searchTerms) + if searchTermTable and (#searchTermTable > 0) then + currSearchTerms = searchTermTable + else + currSearchTerms = nil + end + + if searchTermTable == nil then + showEntireGrid() + return + end + + local filteredButtons = filterGear(currSearchTerms) + showPartialGrid(filteredButtons) +end + +function nukeBackpack() + while #buttons > 0 do + table.remove(buttons) + end + buttons = {} + while #backpackItems > 0 do + table.remove(backpackItems) + end + backpackItems = {} + local scrollingFrameChildren = grid.ScrollingFrame:GetChildren() + for i = 1, #scrollingFrameChildren do + scrollingFrameChildren[i]:remove() + end +end + +function getGearContextMenu() + local gearContextMenu = Instance.new("Frame") + gearContextMenu.Active = true + gearContextMenu.Name = "UnequipContextMenu" + gearContextMenu.Size = UDim2.new(0,115,0,70) + gearContextMenu.Position = UDim2.new(0,-16,0,-16) + gearContextMenu.BackgroundTransparency = 1 + gearContextMenu.Visible = false + + local gearContextMenuButton = Instance.new("TextButton") + gearContextMenuButton.Name = "UnequipContextMenuButton" + gearContextMenuButton.Text = "" + gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault + gearContextMenuButton.ZIndex = 8 + gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20) + gearContextMenuButton.Visible = true + gearContextMenuButton.Parent = gearContextMenu + + local elementHeight = 12 + + local contextMenuElements = {} + local contextMenuElementsName = {"Remove Hotkey"} + + for i = 1, #contextMenuElementsName do + local element = {} + element.Type = "Button" + element.Text = contextMenuElementsName[i] + element.Action = i + element.DoIt = UnequipGearMenuClick + table.insert(contextMenuElements,element) + end + + for i, contextElement in ipairs(contextMenuElements) do + local element = contextElement + if element.Type == "Button" then + local button = Instance.new("TextButton") + button.Name = "UnequipContextButton" .. i + button.BackgroundColor3 = Color3.new(0,0,0) + button.BorderSizePixel = 0 + button.TextXAlignment = Enum.TextXAlignment.Left + button.Text = " " .. contextElement.Text + button.Font = Enum.Font.Arial + button.FontSize = Enum.FontSize.Size14 + button.Size = UDim2.new(1, 8, 0, elementHeight) + button.Position = UDim2.new(0,0,0,elementHeight * i) + button.TextColor3 = Color3.new(1,1,1) + button.ZIndex = 9 + button.Parent = gearContextMenuButton + + button.MouseButton1Click:connect(function() + if button.Active and not gearContextMenu.Parent.Active then + local success, result = pcall(function() element.DoIt(element, gearContextMenu) end) + browsingMenu = false + gearContextMenu.Visible = false + clearHighlight(button) + clearPreview() + end + end) + + button.MouseEnter:connect(function() + if button.Active and gearContextMenu.Parent.Active then + highlight(button) + end + end) + button.MouseLeave:connect(function() + if button.Active and gearContextMenu.Parent.Active then + clearHighlight(button) + end + end) + + contextElement.Button = button + contextElement.Element = button + elseif element.Type == "Label" then + local frame = Instance.new("Frame") + frame.Name = "ContextLabel" .. i + frame.BackgroundTransparency = 1 + frame.Size = UDim2.new(1, 8, 0, elementHeight) + + local label = Instance.new("TextLabel") + label.Name = "Text1" + label.BackgroundTransparency = 1 + label.BackgroundColor3 = Color3.new(1,1,1) + label.BorderSizePixel = 0 + label.TextXAlignment = Enum.TextXAlignment.Left + label.Font = Enum.Font.ArialBold + label.FontSize = Enum.FontSize.Size14 + label.Position = UDim2.new(0.0, 0, 0, 0) + label.Size = UDim2.new(0.5, 0, 1, 0) + label.TextColor3 = Color3.new(1,1,1) + label.ZIndex = 9 + label.Parent = frame + element.Label1 = label + + if element.GetText2 then + label = Instance.new("TextLabel") + label.Name = "Text2" + label.BackgroundTransparency = 1 + label.BackgroundColor3 = Color3.new(1,1,1) + label.BorderSizePixel = 0 + label.TextXAlignment = Enum.TextXAlignment.Right + label.Font = Enum.Font.Arial + label.FontSize = Enum.FontSize.Size14 + label.Position = UDim2.new(0.5, 0, 0, 0) + label.Size = UDim2.new(0.5, 0, 1, 0) + label.TextColor3 = Color3.new(1,1,1) + label.ZIndex = 9 + label.Parent = frame + element.Label2 = label + end + frame.Parent = gearContextMenuButton + element.Label = frame + element.Element = frame + end + end + + gearContextMenu.ZIndex = 4 + gearContextMenu.MouseLeave:connect(function() + browsingMenu = false + gearContextMenu.Visible = false + clearPreview() + end) + robloxLock(gearContextMenu) + + return gearContextMenu +end + +local backpackChildren = player.Backpack:GetChildren() +for i = 1, #backpackChildren do + addToGrid(backpackChildren[i]) +end + +------------------------- Start Lifelong Connections ----------------------- + + +resizeEvent.Event:connect(function(absSize) + if debounce then return end + + debounce = true + wait() + resize() + resizeGrid() + debounce = false +end) + +currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end) +currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end) + +currentLoadout.DescendantAdded:connect(function(descendant) + if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then + centerGear(currentLoadout:GetChildren()) + end +end) +currentLoadout.DescendantRemoving:connect(function(descendant) + if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then + wait() + centerGear(currentLoadout:GetChildren()) + end +end) + +grid.MouseEnter:connect(function() clearPreview() end) +grid.MouseLeave:connect(function() clearPreview() end) + +player.CharacterRemoving:connect(function() + removeCharacterConnections() + nukeBackpack() +end) +player.CharacterAdded:connect(function() setupCharacterConnections() end) + +player.ChildAdded:connect(function(child) + if child:IsA("Backpack") then + playerBackpack = child + if backpackAddCon then backpackAddCon:disconnect() end + backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) + end +end) + +swapSlot.Changed:connect(function() + if not swapSlot.Value then + updateGridActive() + end +end) + +local loadoutChildren = currentLoadout:GetChildren() +for i = 1, #loadoutChildren do + if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then + loadoutChildren[i].ChildRemoved:connect(function() + updateGridActive() + end) + loadoutChildren[i].ChildAdded:connect(function() + updateGridActive() + end) + end +end +------------------------- End Lifelong Connections ----------------------- + +resize() +resizeGrid() + +-- make sure any items in the loadout are accounted for in inventory +local loadoutChildren = currentLoadout:GetChildren() +for i = 1, #loadoutChildren do + loadoutCheck(loadoutChildren[i], false) +end +if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end + +-- make sure that inventory is listening to gear reparenting +if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then + setupCharacterConnections() +end +if not backpackAddCon then + backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) +end + +backpackOpenEvent.Event:connect(backpackOpenHandler) +backpackCloseEvent.Event:connect(backpackCloseHandler) +tabClickedEvent.Event:connect(tabClickHandler) +searchRequestedEvent.Event:connect(showSearchGear) + +recalculateScrollLoadout() \ No newline at end of file diff --git a/public/asset/14 b/public/asset/14 index 117cf43..91731d8 100644 --- a/public/asset/14 +++ b/public/asset/14 @@ -1,863 +1,880 @@ -%14% --- A couple of necessary functions -local function waitForChild(instance, name) - assert(instance) - assert(name) - while not instance:FindFirstChild(name) do - print('Waiting for ...', instance, name) - instance.ChildAdded:wait() - end - return instance:FindFirstChild(name) -end -local function waitForProperty(instance, property) - assert(instance) - assert(property) - while not instance[property] do - instance.Changed:wait() - end -end - -local function IsTouchDevice() - local touchEnabled = false - pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end) - return touchEnabled -end - - -waitForChild(game,"Players") -waitForProperty(game.Players,"LocalPlayer") -local player = game.Players.LocalPlayer - -local RbxGui, msg = LoadLibrary("RbxGui") -if not RbxGui then print("could not find RbxGui!") return end - ---- Begin Locals -local StaticTabName = "gear" - -local backpack = script.Parent -local screen = script.Parent.Parent - -local backpackItems = {} -local buttons = {} - -local debounce = false -local browsingMenu = false - -local mouseEnterCons = {} -local mouseClickCons = {} - -local characterChildAddedCon = nil -local characterChildRemovedCon = nil -local backpackAddCon = nil - -local playerBackpack = waitForChild(player,"Backpack") - -waitForChild(backpack,"Tabs") - -waitForChild(backpack,"Gear") -local gearPreview = waitForChild(backpack.Gear,"GearPreview") - -local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea") - -local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout") - -local grid = waitForChild(backpack.Gear,"GearGrid") -local gearButton = waitForChild(grid,"GearButton") - -local swapSlot = waitForChild(script.Parent,"SwapSlot") - -local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager") -local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent") -local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent") -local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent") -local resizeEvent = waitForChild(backpackManager,"ResizeEvent") -local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent") -local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady") - --- creating scroll bar early as to make sure items get placed correctly -local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(6, 6)) - -scrollFrame.Position = UDim2.new(0,0,0,30) -scrollFrame.Size = UDim2.new(1,0,1,-30) -scrollFrame.Parent = backpack.Gear.GearGrid - -local scrollBar = Instance.new("Frame") -scrollBar.Name = "ScrollBar" -scrollBar.BackgroundTransparency = 0.9 -scrollBar.BackgroundColor3 = Color3.new(1,1,1) -scrollBar.BorderSizePixel = 0 -scrollBar.Size = UDim2.new(0, 17, 1, -36) -scrollBar.Position = UDim2.new(0,0,0,18) -scrollBar.Parent = scroller - -scrollDown.Position = UDim2.new(0,0,1,-17) - -scrollUp.Parent = scroller -scrollDown.Parent = scroller - -local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame() - -scrollFrameLoadout.Position = UDim2.new(0,0,0,0) -scrollFrameLoadout.Size = UDim2.new(1,0,1,0) -scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList - -local LoadoutButton = Instance.new("TextButton") -LoadoutButton.RobloxLocked = true -LoadoutButton.Name = "LoadoutButton" -LoadoutButton.Font = Enum.Font.ArialBold -LoadoutButton.FontSize = Enum.FontSize.Size14 -LoadoutButton.Position = UDim2.new(0,0,0,0) -LoadoutButton.Size = UDim2.new(1,0,0,32) -LoadoutButton.Style = Enum.ButtonStyle.RobloxButton -LoadoutButton.Text = "Loadout #1" -LoadoutButton.TextColor3 = Color3.new(1,1,1) -LoadoutButton.Parent = scrollFrameLoadout - -local LoadoutButtonTwo = LoadoutButton:clone() -LoadoutButtonTwo.Text = "Loadout #2" -LoadoutButtonTwo.Parent = scrollFrameLoadout - -local LoadoutButtonThree = LoadoutButton:clone() -LoadoutButtonThree.Text = "Loadout #3" -LoadoutButtonThree.Parent = scrollFrameLoadout - -local LoadoutButtonFour = LoadoutButton:clone() -LoadoutButtonFour.Text = "Loadout #4" -LoadoutButtonFour.Parent = scrollFrameLoadout - -local scrollBarLoadout = Instance.new("Frame") -scrollBarLoadout.Name = "ScrollBarLoadout" -scrollBarLoadout.BackgroundTransparency = 0.9 -scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1) -scrollBarLoadout.BorderSizePixel = 0 -scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36) -scrollBarLoadout.Position = UDim2.new(0,0,0,18) -scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea - -scrollDownLoadout.Position = UDim2.new(0,0,1,-17) - -scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea -scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea - - --- Begin Functions -function removeFromMap(map,object) - for i = 1, #map do - if map[i] == object then - table.remove(map,i) - break - end - end -end - -function robloxLock(instance) - instance.RobloxLocked = true - children = instance:GetChildren() - if children then - for i, child in ipairs(children) do - robloxLock(child) - end - end -end - -function resize() - local size = 0 - if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then - size = gearPreview.AbsoluteSize.X * 0.75 - else - size = gearPreview.AbsoluteSize.Y * 0.75 - end - - waitForChild(gearPreview,"GearImage") - gearPreview.GearImage.Size = UDim2.new(0,size,0,size) - gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size) - - resizeGrid() -end - -function addToGrid(child) - if not child:IsA("Tool") then - if not child:IsA("HopperBin") then - return - end - end - if child:FindFirstChild("RobloxBuildTool") then return end - - for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered - if v == child then return end - end - - table.insert(backpackItems,child) - - local changeCon = child.Changed:connect(function(prop) - if prop == "Name" then - if buttons[child] then - if buttons[child].Image == "" then - buttons[child].GearText.Text = child.Name - end - end - end - end) - local ancestryCon = nil - ancestryCon = child.AncestryChanged:connect(function(theChild,theParent) - local thisObject = nil - for k,v in pairs(backpackItems) do - if v == child then - thisObject = v - break - end - end - - waitForProperty(player,"Character") - waitForChild(player,"Backpack") - if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then - if ancestryCon then ancestryCon:disconnect() end - if changeCon then changeCon:disconnect() end - - for k,v in pairs(backpackItems) do - if v == thisObject then - if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end - if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end - buttons[v].Parent = nil - buttons[v] = nil - break - end - end - - removeFromMap(backpackItems,thisObject) - - resizeGrid() - else - resizeGrid() - end - updateGridActive() - end) - resizeGrid() -end - -function buttonClick(button) - if button:FindFirstChild("UnequipContextMenu") and not button.Active then - button.UnequipContextMenu.Visible = true - browsingMenu = true - end -end - -function previewGear(button) - if not browsingMenu then - gearPreview.Visible = false - gearPreview.GearImage.Image = button.Image - gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name - end -end - -function findEmptySlot() - local smallestNum = nil - local loadout = currentLoadout:GetChildren() - for i = 1, #loadout do - if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then - local frameNum = tonumber(string.sub(loadout[i].Name,5)) - if frameNum == 0 then frameNum = 10 end - if not smallestNum or (smallestNum > frameNum) then - smallestNum = frameNum - end - end - end - if smallestNum == 10 then smallestNum = 0 end - return smallestNum -end - -function checkForSwap(button,x,y) - local loadoutChildren = currentLoadout:GetChildren() - for i = 1, #loadoutChildren do - if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then - if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then - if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then - local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) - swapGearSlot(slot,button) - return true - end - end - end - end - return false -end - -function resizeGrid() - for k,v in pairs(backpackItems) do - if not v:FindFirstChild("RobloxBuildTool") then - if not buttons[v] then - local buttonClone = gearButton:clone() - buttonClone.Parent = grid.ScrollingFrame - buttonClone.Visible = true - buttonClone.Image = v.TextureId - if buttonClone.Image == "" then - buttonClone.GearText.Text = v.Name - end - - buttonClone.GearReference.Value = v - buttonClone.Draggable = true - buttons[v] = buttonClone - - - if not IsTouchDevice() then - local unequipMenu = getGearContextMenu() - - - unequipMenu.Visible = false - unequipMenu.Parent = buttonClone - end - - local beginPos = nil - buttonClone.DragBegin:connect(function(value) - waitForChild(buttonClone, 'Background') - buttonClone['Background'].ZIndex = 10 - buttonClone.ZIndex = 10 - beginPos = value - end) - buttonClone.DragStopped:connect(function(x,y) - waitForChild(buttonClone, 'Background') - buttonClone['Background'].ZIndex = 1.0 - buttonClone.ZIndex = 2 - if beginPos ~= buttonClone.Position then - if not checkForSwap(buttonClone,x,y) then - buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true) - buttonClone.Draggable = false - delay(0.5,function() - buttonClone.Draggable = true - end) - else - buttonClone.Position = beginPos - end - end - end) - local clickTime = tick() - mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end) - mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() - local newClickTime = tick() - if buttonClone.Active and (newClickTime - clickTime) < 0.5 then - local slot = findEmptySlot() - if slot then - buttonClone.ZIndex = 1 - swapGearSlot(slot,buttonClone) - end - else - buttonClick(buttonClone) - end - clickTime = newClickTime - end) - end - end - end - recalculateScroll() -end - -function showPartialGrid(subset) - for k,v in pairs(buttons) do - v.Parent = nil - end - if subset then - for k,v in pairs(subset) do - v.Parent = grid.ScrollingFrame - end - end - recalculateScroll() -end - -function showEntireGrid() - for k,v in pairs(buttons) do - v.Parent = grid.ScrollingFrame - end - recalculateScroll() -end - -function inLoadout(gear) - local children = currentLoadout:GetChildren() - for i = 1, #children do - if children[i]:IsA("Frame") then - local button = children[i]:GetChildren() - if #button > 0 then - if button[1].GearReference.Value and button[1].GearReference.Value == gear then - return true - end - end - end - end - return false -end - -function updateGridActive() - for k,v in pairs(backpackItems) do - if buttons[v] then - local gear = nil - local gearRef = buttons[v]:FindFirstChild("GearReference") - - if gearRef then gear = gearRef.Value end - - if not gear then - buttons[v].Active = false - elseif inLoadout(gear) then - buttons[v].Active = false - else - buttons[v].Active = true - end - end - end -end - -function centerGear(loadoutChildren) - local gearButtons = {} - local lastSlotAdd = nil - for i = 1, #loadoutChildren do - if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then - if loadoutChildren[i].Name == "Slot0" then - lastSlotAdd = loadoutChildren[i] - else - table.insert(gearButtons, loadoutChildren[i]) - end - end - end - if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end - - local startPos = ( 1 - (#gearButtons * 0.1) ) / 2 - for i = 1, #gearButtons do - gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) - end -end - -function tabClickHandler(tabName) - if tabName == StaticTabName then - backpackOpenHandler(tabName) - else - backpackCloseHandler(tabName) - end -end - -function backpackOpenHandler(currentTab) - if currentTab and currentTab ~= StaticTabName then - backpack.Gear.Visible = false - return - end - - backpack.Gear.Visible = true - updateGridActive() - - resizeGrid() - resize() - tellBackpackReadyFunc:Invoke() -end - -function backpackCloseHandler(currentTab) - if currentTab and currentTab ~= StaticTabName then - backpack.Gear.Visible = false - return - end - - backpack.Gear.Visible = false - - resizeGrid() - resize() - tellBackpackReadyFunc:Invoke() -end - -function loadoutCheck(child, selectState) - if not child:IsA("ImageButton") then return end - for k,v in pairs(backpackItems) do - if buttons[v] then - if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then - if buttons[v].GearReference.Value == child.GearReference.Value then - buttons[v].Active = selectState - break - end - end - end - end -end - -function clearPreview() - gearPreview.GearImage.Image = "" - gearPreview.GearStats.GearName.Text = "" -end - -function removeAllEquippedGear(physGear) - local stuff = player.Character:GetChildren() - for i = 1, #stuff do - if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then - stuff[i].Parent = playerBackpack - end - end -end - -function equipGear(physGear) - removeAllEquippedGear(physGear) - physGear.Parent = player.Character - updateGridActive() -end - -function unequipGear(physGear) - physGear.Parent = playerBackpack - updateGridActive() -end - -function highlight(button) - button.TextColor3 = Color3.new(0,0,0) - button.BackgroundColor3 = Color3.new(0.8,0.8,0.8) -end -function clearHighlight(button) - button.TextColor3 = Color3.new(1,1,1) - button.BackgroundColor3 = Color3.new(0,0,0) -end - -function swapGearSlot(slot,gearButton) - if not swapSlot.Value then -- signal loadout to swap a gear out - swapSlot.Slot.Value = slot - swapSlot.GearButton.Value = gearButton - swapSlot.Value = true - updateGridActive() - end -end - - -local UnequipGearMenuClick = function(element, menu) - if type(element.Action) ~= "number" then return end - local num = element.Action - if num == 1 then -- remove from loadout - unequipGear(menu.Parent.GearReference.Value) - local inventoryButton = menu.Parent - local gearToUnequip = inventoryButton.GearReference.Value - local loadoutChildren = currentLoadout:GetChildren() - local slot = -1 - for i = 1, #loadoutChildren do - if loadoutChildren[i]:IsA("Frame") then - local button = loadoutChildren[i]:GetChildren() - if button[1] and button[1].GearReference.Value == gearToUnequip then - slot = button[1].SlotNumber.Text - break - end - end - end - swapGearSlot(slot,nil) - end -end - -function setupCharacterConnections() - - if backpackAddCon then backpackAddCon:disconnect() end - backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) - - -- make sure we get all the children - local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren() - for i = 1, #backpackChildren do - addToGrid(backpackChildren[i]) - end - - if characterChildAddedCon then characterChildAddedCon:disconnect() end - characterChildAddedCon = - game.Players.LocalPlayer.Character.ChildAdded:connect(function(child) - addToGrid(child) - updateGridActive() - end) - - if characterChildRemovedCon then characterChildRemovedCon:disconnect() end - characterChildRemovedCon = - game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child) - updateGridActive() - end) - - wait() - centerGear(currentLoadout:GetChildren()) -end - -function removeCharacterConnections() - if characterChildAddedCon then characterChildAddedCon:disconnect() end - if characterChildRemovedCon then characterChildRemovedCon:disconnect() end - if backpackAddCon then backpackAddCon:disconnect() end -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function filterGear(terms) - local filteredGear = {} - for k,v in pairs(backpackItems) do - if buttons[v] then - local gearString = string.lower(buttons[v].GearReference.Value.Name) - gearString = trim(gearString) - for i = 1, #terms do - if string.match(gearString,terms[i]) then - table.insert(filteredGear,buttons[v]) - break - end - end - end - end - - return filteredGear -end -function splitByWhitespace(text) - if type(text) ~= "string" then return nil end - - local terms = {} - for token in string.gmatch(text, "[^%s]+") do - if string.len(token) > 0 then - table.insert(terms,token) - end - end - return terms -end -function showSearchGear(searchTerms) - if not backpack.Gear.Visible then return end -- currently not active tab - - local searchTermTable = splitByWhitespace(searchTerms) - if searchTermTable and (#searchTermTable > 0) then - currSearchTerms = searchTermTable - else - currSearchTerms = nil - end - - if searchTermTable == nil then - showEntireGrid() - return - end - - local filteredButtons = filterGear(currSearchTerms) - showPartialGrid(filteredButtons) -end - -function nukeBackpack() - while #buttons > 0 do - table.remove(buttons) - end - buttons = {} - while #backpackItems > 0 do - table.remove(backpackItems) - end - backpackItems = {} - local scrollingFrameChildren = grid.ScrollingFrame:GetChildren() - for i = 1, #scrollingFrameChildren do - scrollingFrameChildren[i]:remove() - end -end - -function getGearContextMenu() - local gearContextMenu = Instance.new("Frame") - gearContextMenu.Active = true - gearContextMenu.Name = "UnequipContextMenu" - gearContextMenu.Size = UDim2.new(0,115,0,70) - gearContextMenu.Position = UDim2.new(0,-16,0,-16) - gearContextMenu.BackgroundTransparency = 1 - gearContextMenu.Visible = false - - local gearContextMenuButton = Instance.new("TextButton") - gearContextMenuButton.Name = "UnequipContextMenuButton" - gearContextMenuButton.Text = "" - gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault - gearContextMenuButton.ZIndex = 8 - gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20) - gearContextMenuButton.Visible = true - gearContextMenuButton.Parent = gearContextMenu - - local elementHeight = 12 - - local contextMenuElements = {} - local contextMenuElementsName = {"Remove Hotkey"} - - for i = 1, #contextMenuElementsName do - local element = {} - element.Type = "Button" - element.Text = contextMenuElementsName[i] - element.Action = i - element.DoIt = UnequipGearMenuClick - table.insert(contextMenuElements,element) - end - - for i, contextElement in ipairs(contextMenuElements) do - local element = contextElement - if element.Type == "Button" then - local button = Instance.new("TextButton") - button.Name = "UnequipContextButton" .. i - button.BackgroundColor3 = Color3.new(0,0,0) - button.BorderSizePixel = 0 - button.TextXAlignment = Enum.TextXAlignment.Left - button.Text = " " .. contextElement.Text - button.Font = Enum.Font.Arial - button.FontSize = Enum.FontSize.Size14 - button.Size = UDim2.new(1, 8, 0, elementHeight) - button.Position = UDim2.new(0,0,0,elementHeight * i) - button.TextColor3 = Color3.new(1,1,1) - button.ZIndex = 9 - button.Parent = gearContextMenuButton - - if not IsTouchDevice() then - - button.MouseButton1Click:connect(function() - if button.Active and not gearContextMenu.Parent.Active then - local success, result = pcall(function() element.DoIt(element, gearContextMenu) end) - browsingMenu = false - gearContextMenu.Visible = false - clearHighlight(button) - clearPreview() - end - end) - - button.MouseEnter:connect(function() - if button.Active and gearContextMenu.Parent.Active then - highlight(button) - end - end) - button.MouseLeave:connect(function() - if button.Active and gearContextMenu.Parent.Active then - clearHighlight(button) - end - end) - end - - contextElement.Button = button - contextElement.Element = button - elseif element.Type == "Label" then - local frame = Instance.new("Frame") - frame.Name = "ContextLabel" .. i - frame.BackgroundTransparency = 1 - frame.Size = UDim2.new(1, 8, 0, elementHeight) - - local label = Instance.new("TextLabel") - label.Name = "Text1" - label.BackgroundTransparency = 1 - label.BackgroundColor3 = Color3.new(1,1,1) - label.BorderSizePixel = 0 - label.TextXAlignment = Enum.TextXAlignment.Left - label.Font = Enum.Font.ArialBold - label.FontSize = Enum.FontSize.Size14 - label.Position = UDim2.new(0.0, 0, 0, 0) - label.Size = UDim2.new(0.5, 0, 1, 0) - label.TextColor3 = Color3.new(1,1,1) - label.ZIndex = 9 - label.Parent = frame - element.Label1 = label - - if element.GetText2 then - label = Instance.new("TextLabel") - label.Name = "Text2" - label.BackgroundTransparency = 1 - label.BackgroundColor3 = Color3.new(1,1,1) - label.BorderSizePixel = 0 - label.TextXAlignment = Enum.TextXAlignment.Right - label.Font = Enum.Font.Arial - label.FontSize = Enum.FontSize.Size14 - label.Position = UDim2.new(0.5, 0, 0, 0) - label.Size = UDim2.new(0.5, 0, 1, 0) - label.TextColor3 = Color3.new(1,1,1) - label.ZIndex = 9 - label.Parent = frame - element.Label2 = label - end - frame.Parent = gearContextMenuButton - element.Label = frame - element.Element = frame - end - end - - gearContextMenu.ZIndex = 4 - gearContextMenu.MouseLeave:connect(function() - browsingMenu = false - gearContextMenu.Visible = false - clearPreview() - end) - robloxLock(gearContextMenu) - - return gearContextMenu -end - -local backpackChildren = player.Backpack:GetChildren() -for i = 1, #backpackChildren do - addToGrid(backpackChildren[i]) -end - -------------------------- Start Lifelong Connections ----------------------- - - -resizeEvent.Event:connect(function(absSize) - if debounce then return end - - debounce = true - wait() - resize() - resizeGrid() - debounce = false -end) - -currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end) -currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end) - -currentLoadout.DescendantAdded:connect(function(descendant) - if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then - centerGear(currentLoadout:GetChildren()) - end -end) -currentLoadout.DescendantRemoving:connect(function(descendant) - if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then - wait() - centerGear(currentLoadout:GetChildren()) - end -end) - -grid.MouseEnter:connect(function() clearPreview() end) -grid.MouseLeave:connect(function() clearPreview() end) - -player.CharacterRemoving:connect(function() - removeCharacterConnections() - nukeBackpack() -end) -player.CharacterAdded:connect(function() setupCharacterConnections() end) - -player.ChildAdded:connect(function(child) - if child:IsA("Backpack") then - playerBackpack = child - if backpackAddCon then backpackAddCon:disconnect() end - backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) - end -end) - -swapSlot.Changed:connect(function() - if not swapSlot.Value then - updateGridActive() - end -end) - -local loadoutChildren = currentLoadout:GetChildren() -for i = 1, #loadoutChildren do - if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then - loadoutChildren[i].ChildRemoved:connect(function() - updateGridActive() - end) - loadoutChildren[i].ChildAdded:connect(function() - updateGridActive() - end) - end -end -------------------------- End Lifelong Connections ----------------------- - -resize() -resizeGrid() - --- make sure any items in the loadout are accounted for in inventory -local loadoutChildren = currentLoadout:GetChildren() -for i = 1, #loadoutChildren do - loadoutCheck(loadoutChildren[i], false) -end -if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end - --- make sure that inventory is listening to gear reparenting -if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then - setupCharacterConnections() -end -if not backpackAddCon then - backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end) -end - -backpackOpenEvent.Event:connect(backpackOpenHandler) -backpackCloseEvent.Event:connect(backpackCloseHandler) -tabClickedEvent.Event:connect(tabClickHandler) -searchRequestedEvent.Event:connect(showSearchGear) - -recalculateScrollLoadout() \ No newline at end of file +%14% +if game.CoreGui.Version < 3 then return end -- peace out if we aren't using the right client + +-- A couple of necessary functions +local function waitForChild(instance, name) + while not instance:FindFirstChild(name) do + instance.ChildAdded:wait() + end + return instance:FindFirstChild(name) +end +local function waitForProperty(instance, property) + while not instance[property] do + instance.Changed:wait() + end +end + +local currentLoadout = script.Parent +local StaticTabName = "gear" + +local robloxGui = game:GetService("CoreGui"):FindFirstChild("RobloxGui") +assert(robloxGui) +waitForChild(robloxGui,"CurrentLoadout") +waitForChild(robloxGui.CurrentLoadout,"TempSlot") +waitForChild(robloxGui.CurrentLoadout.TempSlot,"SlotNumber") + + +--- Begin Locals +waitForChild(game,"Players") +waitForProperty(game.Players,"LocalPlayer") +local player = game.Players.LocalPlayer + +waitForChild(game, "LocalBackpack") +game.LocalBackpack:SetOldSchoolBackpack(false) + +waitForChild(currentLoadout.Parent,"Backpack") +local guiBackpack = currentLoadout.Parent.Backpack + +local backpackManager = waitForChild(guiBackpack,"CoreScripts/BackpackScripts/BackpackManager") +local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent") +local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent") +local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent") +local resizeEvent = waitForChild(backpackManager,"ResizeEvent") + +local inGearTab = true + +local maxNumLoadoutItems = 10 + +local characterChildAddedCon = nil +local backpackChildCon = nil + +local debounce = false + +local enlargeFactor = 1.18 +local buttonSizeEnlarge = UDim2.new(1 * enlargeFactor,0,1 * enlargeFactor,0) +local buttonSizeNormal = UDim2.new(1,0,1,0) +local enlargeOverride = true +local guiTweenSpeed = 0.5 + +local inventory = {} + +for i = 0, 9 do + game:GetService("GuiService"):AddKey(tostring(i)) -- register our keys +end + +local gearSlots = {} +for i = 1, maxNumLoadoutItems do + gearSlots[i] = "empty" +end +--- End Locals + + + + + + +-- Begin Functions +local function kill(prop,con,gear) + if con then con:disconnect() end + if prop == true and gear then + reorganizeLoadout(gear,false) + end +end + +function characterInWorkspace() + if game.Players["LocalPlayer"] then + if game.Players.LocalPlayer["Character"] then + if game.Players.LocalPlayer.Character ~= nil then + if game.Players.LocalPlayer.Character.Parent ~= nil then + return true + end + end + end + end + + return false +end + +function removeGear(gear) + local emptySlot = nil + for i = 1, #gearSlots do + if gearSlots[i] == gear and gear.Parent ~= nil then + emptySlot = i + break + end + end + if emptySlot then + if gearSlots[emptySlot].GearReference.Value then + if gearSlots[emptySlot].GearReference.Value.Parent == game.Players.LocalPlayer.Character then -- if we currently have this equipped, unequip it + gearSlots[emptySlot].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack + end + + if gearSlots[emptySlot].GearReference.Value:IsA("HopperBin") and gearSlots[emptySlot].GearReference.Value.Active then -- this is an active hopperbin + gearSlots[emptySlot].GearReference.Value:Disable() + gearSlots[emptySlot].GearReference.Value.Active = false + end + end + + gearSlots[emptySlot] = "empty" + + local centerizeX = gear.Size.X.Scale/2 + local centerizeY = gear.Size.Y.Scale/2 + gear:TweenSizeAndPosition(UDim2.new(0,0,0,0), + UDim2.new(gear.Position.X.Scale + centerizeX,gear.Position.X.Offset,gear.Position.Y.Scale + centerizeY,gear.Position.Y.Offset), + Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/4,true) + delay(guiTweenSpeed/2, + function() + gear:remove() + end) + end +end + +function insertGear(gear, addToSlot) + local pos = nil + if not addToSlot then + for i = 1, #gearSlots do + if gearSlots[i] == "empty" then + pos = i + break + end + end + + if pos == 1 and gearSlots[1] ~= "empty" then gear:remove() return end -- we are currently full, can't add in + else + pos = addToSlot + -- push all gear down one slot + local start = 1 + for i = 1, #gearSlots do + if gearSlots[i] == "empty" then + start = i + break + end + end + for i = start, pos + 1, -1 do + gearSlots[i] = gearSlots[i - 1] + if i == 10 then + gearSlots[i].SlotNumber.Text = "0" + gearSlots[i].SlotNumberDownShadow.Text = "0" + gearSlots[i].SlotNumberUpShadow.Text = "0" + else + gearSlots[i].SlotNumber.Text = i + gearSlots[i].SlotNumberDownShadow.Text = i + gearSlots[i].SlotNumberUpShadow.Text = i + end + end + end + + gearSlots[pos] = gear + if pos ~= maxNumLoadoutItems then + if(type(tostring(pos)) == "string") then + local posString = tostring(pos) + gear.SlotNumber.Text = posString + gear.SlotNumberDownShadow.Text = posString + gear.SlotNumberUpShadow.Text = posString + end + else -- tenth gear doesn't follow mathematical pattern :( + gear.SlotNumber.Text = "0" + gear.SlotNumberDownShadow.Text = "0" + gear.SlotNumberUpShadow.Text = "0" + end + gear.Visible = true + + local con = nil + con = gear.Kill.Changed:connect(function(prop) kill(prop,con,gear) end) +end + + +function reorganizeLoadout(gear, inserting, equipped, addToSlot) + if inserting then -- add in gear + insertGear(gear, addToSlot) + else + removeGear(gear) + end + if gear ~= "empty" then gear.ZIndex = 1 end +end + +function checkToolAncestry(child,parent) + if child:FindFirstChild("RobloxBuildTool") then return end -- don't show roblox build tools + if child:IsA("Tool") or child:IsA("HopperBin") then + for i = 1, #gearSlots do + if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then + if parent == nil then + gearSlots[i].Kill.Value = true + return false + elseif child.Parent == player.Character then + gearSlots[i].Selected = true + return true + elseif child.Parent == player.Backpack then + if child:IsA("Tool") or child:IsA("HopperBin") then gearSlots[i].Selected = false end + return true + else + gearSlots[i].Kill.Value = true + return false + end + return true + end + end + end +end + +function removeAllEquippedGear(physGear) + local stuff = player.Character:GetChildren() + for i = 1, #stuff do + if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then + if stuff[i]:IsA("Tool") then stuff[i].Parent = player.Backpack end + if stuff[i]:IsA("HopperBin") then + stuff[i]:Disable() + end + end + end +end + +function hopperBinSwitcher(numKey, physGear) + if not physGear then return end + + physGear:ToggleSelect() + + if gearSlots[numKey] == "empty" then return end + + if not physGear.Active then + gearSlots[numKey].Selected = false + normalizeButton(gearSlots[numKey]) + else + gearSlots[numKey].Selected = true + enlargeButton(gearSlots[numKey]) + end +end + +function toolSwitcher(numKey) + + if not gearSlots[numKey] then return end + local physGear = gearSlots[numKey].GearReference.Value + if physGear == nil then return end + + removeAllEquippedGear(physGear) -- we don't remove this gear, as then we get a double switcheroo + + local key = numKey + if numKey == 0 then key = 10 end + + for i = 1, #gearSlots do + if gearSlots[i] and gearSlots[i] ~= "empty" and i ~= key then + normalizeButton(gearSlots[i]) + gearSlots[i].Selected = false + if gearSlots[i].GearReference and gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value:IsA("HopperBin") and gearSlots[i].GearReference.Value.Active then + gearSlots[i].GearReference.Value:ToggleSelect() + end + end + end + + if physGear:IsA("HopperBin") then + hopperBinSwitcher(numKey,physGear) + else + if physGear.Parent == player.Character then + physGear.Parent = player.Backpack + + if gearSlots[numKey] ~= "empty" then + gearSlots[numKey].Selected = false + normalizeButton(gearSlots[numKey]) + end + else + --player.Character.Humanoid:EquipTool(physGear) + + physGear.Parent = player.Character + gearSlots[numKey].Selected = true + + enlargeButton(gearSlots[numKey]) + end + end +end + + +function activateGear(num) + local numKey = nil + if num == "0" then + numKey = 10 -- why do lua indexes have to start at 1? :( + else + numKey = tonumber(num) + end + + if(numKey == nil) then return end + + if gearSlots[numKey] ~= "empty" then + toolSwitcher(numKey) + end +end + + +enlargeButton = function(button) + if button.Size.Y.Scale > 1 then return end + if not button.Parent then return end + if not button.Selected then return end + + for i = 1, #gearSlots do + if gearSlots[i] == "empty" then break end + if gearSlots[i] ~= button then + normalizeButton(gearSlots[i]) + end + end + + if not enlargeOverride then + return + end + + if button:IsA("ImageButton") or button:IsA("TextButton") then + button.ZIndex = 2 + local centerizeX = -(buttonSizeEnlarge.X.Scale - button.Size.X.Scale)/2 + local centerizeY = -(buttonSizeEnlarge.Y.Scale - button.Size.Y.Scale)/2 + button:TweenSizeAndPosition(buttonSizeEnlarge, + UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset), + Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/5,enlargeOverride) + end +end + +normalizeAllButtons = function() + for i = 1, #gearSlots do + if gearSlots[i] == "empty" then break end + if gearSlots[i] ~= button then + normalizeButton(gearSlots[i],0.1) + end + end +end + + +normalizeButton = function(button, speed) + if not button then return end + if button.Size.Y.Scale <= 1 then return end + if button.Selected then return end + if not button.Parent then return end + + local moveSpeed = speed + if moveSpeed == nil or type(moveSpeed) ~= "number" then moveSpeed = guiTweenSpeed/5 end + + if button:IsA("ImageButton") or button:IsA("TextButton") then + button.ZIndex = 1 + local inverseEnlarge = 1/enlargeFactor + local centerizeX = -(buttonSizeNormal.X.Scale - button.Size.X.Scale)/2 + local centerizeY = -(buttonSizeNormal.Y.Scale - button.Size.Y.Scale)/2 + button:TweenSizeAndPosition(buttonSizeNormal, + UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset), + Enum.EasingDirection.Out, Enum.EasingStyle.Quad,moveSpeed,enlargeOverride) + end +end + +local waitForDebounce = function() + while debounce do + wait() + end +end + +function pointInRectangle(point,rectTopLeft,rectSize) + if point.x > rectTopLeft.x and point.x < (rectTopLeft.x + rectSize.x) then + if point.y > rectTopLeft.y and point.y < (rectTopLeft.y + rectSize.y) then + return true + end + end + return false +end + +function swapGear(gearClone,toFrame) + local toFrameChildren = toFrame:GetChildren() + if #toFrameChildren == 1 then + if toFrameChildren[1]:FindFirstChild("SlotNumber") then + + local toSlot = tonumber(toFrameChildren[1].SlotNumber.Text) + local gearCloneSlot = tonumber(gearClone.SlotNumber.Text) + if toSlot == 0 then toSlot = 10 end + if gearCloneSlot == 0 then gearCloneSlot = 10 end + + gearSlots[toSlot] = gearClone + gearSlots[gearCloneSlot] = toFrameChildren[1] + + toFrameChildren[1].SlotNumber.Text = gearClone.SlotNumber.Text + toFrameChildren[1].SlotNumberDownShadow.Text = gearClone.SlotNumber.Text + toFrameChildren[1].SlotNumberUpShadow.Text = gearClone.SlotNumber.Text + + local subString = string.sub(toFrame.Name,5) + gearClone.SlotNumber.Text = subString + gearClone.SlotNumberDownShadow.Text = subString + gearClone.SlotNumberUpShadow.Text = subString + + gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0) + toFrameChildren[1].Position = UDim2.new(toFrameChildren[1].Position.X.Scale,0,toFrameChildren[1].Position.Y.Scale,0) + + toFrameChildren[1].Parent = gearClone.Parent + gearClone.Parent = toFrame + end + else + local slotNum = tonumber(gearClone.SlotNumber.Text) + if slotNum == 0 then slotNum = 10 end + gearSlots[slotNum] = "empty" -- reset this gear slot + + local subString = string.sub(toFrame.Name,5) + gearClone.SlotNumber.Text = subString + gearClone.SlotNumberDownShadow.Text = subString + gearClone.SlotNumberUpShadow.Text = subString + + local toSlotNum = tonumber(gearClone.SlotNumber.Text) + if toSlotNum == 0 then toSlotNum = 10 end + gearSlots[toSlotNum] = gearClone + gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0) + gearClone.Parent = toFrame + end +end + +function resolveDrag(gearClone,x,y) + local mousePoint = Vector2.new(x,y) + + local frame = gearClone.Parent + local frames = frame.Parent:GetChildren() + + for i = 1, #frames do + if frames[i]:IsA("Frame") then + if pointInRectangle(mousePoint, frames[i].AbsolutePosition,frames[i].AbsoluteSize) then + swapGear(gearClone,frames[i]) + return true + end + end + end + + if x < frame.AbsolutePosition.x or x > ( frame.AbsolutePosition.x + frame.AbsoluteSize.x ) then + reorganizeLoadout(gearClone,false) + return false + elseif y < frame.AbsolutePosition.y or y > ( frame.AbsolutePosition.y + frame.AbsoluteSize.y ) then + reorganizeLoadout(gearClone,false) + return false + else + if dragBeginPos then gearClone.Position = dragBeginPos end + return -1 + end +end + +function unequipAllItems(dontEquipThis) + for i = 1, #gearSlots do + if gearSlots[i] == "empty" then break end + if gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value ~= dontEquipThis then + if gearSlots[i].GearReference.Value:IsA("HopperBin") then + gearSlots[i].GearReference.Value:Disable() + elseif gearSlots[i].GearReference.Value:IsA("Tool") then + gearSlots[i].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack + end + gearSlots[i].Selected = false + end + end +end + +function showToolTip(button, tip) + if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then + button.ToolTipLabel.Text = tostring(tip) + local xSize = button.ToolTipLabel.TextBounds.X + 6 + button.ToolTipLabel.Size = UDim2.new(0,xSize,0,20) + button.ToolTipLabel.Position = UDim2.new(0.5,-xSize/2,0,-30) + button.ToolTipLabel.Visible = true + end +end + +function hideToolTip(button, tip) + if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then + button.ToolTipLabel.Visible = false + end +end + +local addingPlayerChild = function(child, equipped, addToSlot, inventoryGearButton) + waitForDebounce() + debounce = true + + if child:FindFirstChild("RobloxBuildTool") then debounce = false return end -- don't show roblox build tools + if not child:IsA("Tool") then + if not child:IsA("HopperBin") then + debounce = false + return -- we don't care about anything besides tools (sigh...) + end + end + + if not addToSlot then + for i = 1, #gearSlots do + if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then -- we already have gear, do nothing + debounce = false + return + end + end + end + + + local gearClone = currentLoadout.TempSlot:clone() + gearClone.Name = child.Name + gearClone.GearImage.Image = child.TextureId + if gearClone.GearImage.Image == "" then + gearClone.GearText.Text = child.Name + end + gearClone.GearReference.Value = child + + gearClone.MouseEnter:connect(function() + if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then + showToolTip(gearClone, gearClone.GearReference.Value.ToolTip) + end + end) + + gearClone.MouseLeave:connect(function() + if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then + hideToolTip(gearClone, gearClone.GearReference.Value.ToolTip) + end + end) + + gearClone.RobloxLocked = true + + local slotToMod = -1 + + if not addToSlot then + for i = 1, #gearSlots do + if gearSlots[i] == "empty" then + slotToMod = i + break + end + end + else + slotToMod = addToSlot + end + + if slotToMod == - 1 then -- No available slot to add in! + debounce = false + return + end + + local slotNum = slotToMod % 10 + local parent = currentLoadout:FindFirstChild("Slot"..tostring(slotNum)) + gearClone.Parent = parent + + if inventoryGearButton then + local absolutePositionFinal = inventoryGearButton.AbsolutePosition + local currentAbsolutePosition = gearClone.AbsolutePosition + local diff = absolutePositionFinal - currentAbsolutePosition + gearClone.Position = UDim2.new(gearClone.Position.X.Scale,diff.x,gearClone.Position.Y.Scale,diff.y) + gearClone.ZIndex = 4 + end + + if addToSlot then + reorganizeLoadout(gearClone, true, equipped, addToSlot) + else + reorganizeLoadout(gearClone, true) + end + + if gearClone.Parent == nil then debounce = false return end -- couldn't fit in (hopper is full!) + + if equipped then + gearClone.Selected = true + unequipAllItems(child) + delay(guiTweenSpeed + 0.01,function() -- if our gear is equipped, we will want to enlarge it when done moving + if gearClone:FindFirstChild("GearReference") and ( (gearClone.GearReference.Value:IsA("Tool") and gearClone.GearReference.Value.Parent == player.Character) or + (gearClone.GearReference.Value:IsA("HopperBin") and gearClone.GearReference.Value.Active == true) ) then + enlargeButton(gearClone) + end + end) + end + + local dragBeginPos = nil + local clickCon, buttonDeleteCon, mouseEnterCon, mouseLeaveCon, dragStop, dragBegin = nil + clickCon = gearClone.MouseButton1Click:connect(function() + if characterInWorkspace() then + if not gearClone.Draggable then + activateGear(gearClone.SlotNumber.Text) + end + end + end) + mouseEnterCon = gearClone.MouseEnter:connect(function() + if guiBackpack.Visible then + gearClone.Draggable = true + end + end) + dragBegin = gearClone.DragBegin:connect(function(pos) + dragBeginPos = pos + gearClone.ZIndex = 7 + local children = gearClone:GetChildren() + for i = 1, #children do + if children[i]:IsA("TextLabel") then + if string.find(children[i].Name,"Shadow") then + children[i].ZIndex = 8 + else + children[i].ZIndex = 9 + end + elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then + children[i].ZIndex = 7 + end + end + end) + dragStop = gearClone.DragStopped:connect(function(x,y) + if gearClone.Selected then + gearClone.ZIndex = 2 + else + gearClone.ZIndex = 1 + end + local children = gearClone:GetChildren() + for i = 1, #children do + if children[i]:IsA("TextLabel") then + if string.find(children[i].Name,"Shadow") then + children[i].ZIndex = 3 + else + children[i].ZIndex = 4 + end + elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then + children[i].ZIndex = 2 + end + end + resolveDrag(gearClone,x,y) + end) + mouseLeaveCon = gearClone.MouseLeave:connect(function() + gearClone.Draggable = false + end) + buttonDeleteCon = gearClone.AncestryChanged:connect(function() + if gearClone.Parent and gearClone.Parent.Parent == currentLoadout then return end + if clickCon then clickCon:disconnect() end + if buttonDeleteCon then buttonDeleteCon:disconnect() end + if mouseEnterCon then mouseEnterCon:disconnect() end + if mouseLeaveCon then mouseLeaveCon:disconnect() end + if dragStop then dragStop:disconnect() end + if dragBegin then dragBegin:disconnect() end + end) -- this probably isn't necessary since objects are being deleted (probably), but this might still leak just in case + + local childCon = nil + local childChangeCon = nil + childCon = child.AncestryChanged:connect(function(newChild,parent) + if not checkToolAncestry(newChild,parent) then + if childCon then childCon:disconnect() end + if childChangeCon then childChangeCon:disconnect() end + removeFromInventory(child) + elseif parent == game.Players.LocalPlayer.Backpack then + normalizeButton(gearClone) + end + end) + + childChangeCon = child.Changed:connect(function(prop) + if prop == "Name" then + if gearClone and gearClone.GearImage.Image == "" then + gearClone.GearText.Text = child.Name + end + elseif prop == "Active" then + if child and child:IsA("HopperBin") then + if not child.Active then + gearClone.Selected = false + normalizeButton(gearClone) + end + end + elseif prop == "TextureId" then + gearClone.GearImage.Image = child.TextureId + end + end) + + debounce = false + +end + +function addToInventory(child) + if not child:IsA("Tool") or not child:IsA("HopperBin") then return end + + local slot = nil + for i = 1, #inventory do + if inventory[i] and inventory[i] == child then return end + if not inventory[i] then slot = i end + end + if slot then + inventory[slot] = child + elseif #inventory < 1 then + inventory[1] = child + else + inventory[#inventory + 1] = child + end +end + +function removeFromInventory(child) + for i = 1, #inventory do + if inventory[i] == child then + table.remove(inventory,i) + inventory[i] = nil + end + end +end + +local spreadOutGear = function() + loadoutChildren = currentLoadout:GetChildren() + + for i = 1, #loadoutChildren do + if loadoutChildren[i]:IsA("Frame") then + loadoutChildren[i].BackgroundTransparency = 0.5 + local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) + if slot == 0 then slot = 10 end + loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) + end + end +end + +local centerGear = function() + loadoutChildren = currentLoadout:GetChildren() + local gearButtons = {} + local lastSlotAdd = nlii + + for i = 1, #loadoutChildren do + if loadoutChildren[i]:IsA("Frame") then + if #loadoutChildren[i]:GetChildren() > 0 then + if loadoutChildren[i].Name == "Slot0" then + lastSlotAdd = loadoutChildren[i] + else + table.insert(gearButtons, loadoutChildren[i]) + end + end + loadoutChildren[i].BackgroundTransparency = 1 + end + end + if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end + + local startPos = ( 1 - (#gearButtons * 0.1) ) / 2 + for i = 1, #gearButtons do + gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) + end +end + +function editLoadout() + if inGearTab then + spreadOutGear() + end +end + +function readonlyLoadout() + if not inGearTab then + centerGear() + end +end + +function setupBackpackListener() + if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end + backpackChildCon = player.Backpack.ChildAdded:connect(function(child) + addingPlayerChild(child) + addToInventory(child) + end) +end + +function playerCharacterChildAdded(child) + addingPlayerChild(child,true) + addToInventory(child) +end + +function activateLoadout() + currentLoadout.Visible = true +end + +function deactivateLoadout() + currentLoadout.Visible = false +end + +function tabHandler(inFocus) + inGearTab = inFocus + if inFocus then + editLoadout() + else + readonlyLoadout() + end +end +-- End Functions + + + + + + +-- Begin Script +wait() -- let stuff initialize incase this is first heartbeat... + +waitForChild(player,"Backpack") +waitForProperty(player,"Character") +local backpackChildren = player.Backpack:GetChildren() +local size = math.min(10,#backpackChildren) +for i = 1, size do + addingPlayerChild(backpackChildren[i],false) +end +setupBackpackListener() + +waitForProperty(player,"Character") +for i,v in ipairs(player.Character:GetChildren()) do + playerCharacterChildAdded(v) +end +characterChildAddedCon = player.Character.ChildAdded:connect(function(child) playerCharacterChildAdded(child) end) + +waitForChild(player.Character,"Humanoid") +humanoidDiedCon = player.Character.Humanoid.Died:connect(function() + if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end + deactivateLoadout() + if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end +end) + +player.CharacterRemoving:connect(function() + for i = 1, #gearSlots do + if gearSlots[i] ~= "empty" then + gearSlots[i].Parent = nil + gearSlots[i] = "empty" + end + end +end) + +player.CharacterAdded:connect(function() + waitForProperty(game.Players,"LocalPlayer") + player = game.Players.LocalPlayer -- make sure we are still looking at the correct character + waitForChild(player,"Backpack") + + + delay(1,function() + local backpackChildren = player.Backpack:GetChildren() + local size = math.min(10,#backpackChildren) + for i = 1, size do + addingPlayerChild(backpackChildren[i],false) + end + setupBackpackListener() + end) + + activateLoadout() + + if characterChildAddedCon then + characterChildAddedCon:disconnect() + characterChildAddedCon = nil + end + + characterChildAddedCon = + player.Character.ChildAdded:connect(function(child) + addingPlayerChild(child,true) + end) + + waitForChild(player.Character,"Humanoid") + humanoidDiedCon = + player.Character.Humanoid.Died:connect(function() + deactivateLoadout() + + if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end + if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end + end) + +end) + +waitForChild(guiBackpack,"SwapSlot") +guiBackpack.SwapSlot.Changed:connect(function() + if guiBackpack.SwapSlot.Value then + local swapSlot = guiBackpack.SwapSlot + local pos = swapSlot.Slot.Value + if pos == 0 then pos = 10 end + if gearSlots[pos] then + reorganizeLoadout(gearSlots[pos],false) + end + if swapSlot.GearButton.Value then + addingPlayerChild(swapSlot.GearButton.Value.GearReference.Value,false,pos) + end + guiBackpack.SwapSlot.Value = false + end +end) + +game:GetService("GuiService").KeyPressed:connect(function(key) + if characterInWorkspace() then + activateGear(key) + end +end) + +backpackOpenEvent.Event:connect(editLoadout) +backpackCloseEvent.Event:connect(centerGear) +tabClickedEvent.Event:connect(function ( tabName ) + tabHandler(tabName == StaticTabName) +end) \ No newline at end of file diff --git a/public/asset/15 b/public/asset/15 index 7e2c614..e21dcce 100644 --- a/public/asset/15 +++ b/public/asset/15 @@ -1,1021 +1,247 @@ -%15% -if game.CoreGui.Version < 3 then return end -- peace out if we aren't using the right client - --- A couple of necessary functions -local function waitForChild(instance, name) - while not instance:FindFirstChild(name) do - instance.ChildAdded:wait() - end - return instance:FindFirstChild(name) -end -local function waitForProperty(instance, property) - while not instance[property] do - instance.Changed:wait() - end -end - -local currentLoadout = script.Parent -local StaticTabName = "gear" - -local robloxGui = game:GetService("CoreGui"):FindFirstChild("RobloxGui") -assert(robloxGui) -local controlFrame = waitForChild(robloxGui, 'ControlFrame') -local backpackButton = waitForChild(controlFrame, 'BackpackButton') -local backpack = waitForChild(robloxGui, 'Backpack') -waitForChild(robloxGui,"CurrentLoadout") -waitForChild(robloxGui.CurrentLoadout,"TempSlot") -waitForChild(robloxGui.CurrentLoadout.TempSlot,"SlotNumber") - -waitForChild(currentLoadout, 'Background') -local clBackground = currentLoadout.Background - -local function IsTouchDevice() - local touchEnabled = false - pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end) - return touchEnabled -end - -local function moveHealthBar(pGui) - waitForChild(pGui, 'HealthGUI') - waitForChild(pGui['HealthGUI'], 'tray') - local tray = pGui['HealthGUI']['tray'] - tray.Position = UDim2.new(0.5, -85, 1, -26) -end - - - ---- Begin Locals -waitForChild(game,"Players") -waitForProperty(game.Players,"LocalPlayer") -local player = game.Players.LocalPlayer - -waitForChild(player, 'PlayerGui') -Spawn(function() - moveHealthBar(player.PlayerGui) -end) - -while player.Character == nil do wait(0.03) end -local humanoid = waitForChild(player.Character, 'Humanoid') -humanoid.Died:connect(function() - backpackButton.Visible = false -end) - -waitForChild(game, "LocalBackpack") -game.LocalBackpack:SetOldSchoolBackpack(false) - -waitForChild(currentLoadout.Parent,"Backpack") -local guiBackpack = currentLoadout.Parent.Backpack - -local backpackManager = waitForChild(guiBackpack,"CoreScripts/BackpackScripts/BackpackManager") -local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent") -local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent") -local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent") -local resizeEvent = waitForChild(backpackManager,"ResizeEvent") - -local inGearTab = true - -local maxNumLoadoutItems = 10 -if robloxGui.AbsoluteSize.Y <= 320 then - maxNumLoadoutItems = 4 -end - - -local characterChildAddedCon = nil -local backpackChildCon = nil - -local debounce = false - -local enlargeFactor = 1.18 -local buttonSizeEnlarge = UDim2.new(1 * enlargeFactor,0,1 * enlargeFactor,0) -local buttonSizeNormal = UDim2.new(1,0,1,0) -local enlargeOverride = true -local guiTweenSpeed = 0.5 - -local firstInstanceOfLoadout = false - -local inventory = {} - -for i = 0, 9 do - game:GetService("GuiService"):AddKey(tostring(i)) -- register our keys -end - -local gearSlots = {} -for i = 1, maxNumLoadoutItems do - gearSlots[i] = "empty" -end - -local backpackWasOpened = false ---- End Locals - - - - - - --- Begin Functions -local function backpackIsOpen() - if guiBackpack then - return guiBackpack.Visible - end - return false -end - - -local function kill(prop,con,gear) - if con then con:disconnect() end - if prop == true and gear then - reorganizeLoadout(gear,false) - end -end - -function characterInWorkspace() - if game.Players["LocalPlayer"] then - if game.Players.LocalPlayer["Character"] then - if game.Players.LocalPlayer.Character ~= nil then - if game.Players.LocalPlayer.Character.Parent ~= nil then - return true - end - end - end - end - - return false -end - -function removeGear(gear) - local emptySlot = nil - for i = 1, #gearSlots do - if gearSlots[i] == gear and gear.Parent ~= nil then - emptySlot = i - break - end - end - if emptySlot then - if gearSlots[emptySlot].GearReference.Value then - if gearSlots[emptySlot].GearReference.Value.Parent == game.Players.LocalPlayer.Character then -- if we currently have this equipped, unequip it - gearSlots[emptySlot].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack - end - - if gearSlots[emptySlot].GearReference.Value:IsA("HopperBin") and gearSlots[emptySlot].GearReference.Value.Active then -- this is an active hopperbin - gearSlots[emptySlot].GearReference.Value:Disable() - gearSlots[emptySlot].GearReference.Value.Active = false - end - end - - gearSlots[emptySlot] = "empty" - - local centerizeX = gear.Size.X.Scale/2 - local centerizeY = gear.Size.Y.Scale/2 - --[[gear:TweenSizeAndPosition(UDim2.new(0,0,0,0), - UDim2.new(gear.Position.X.Scale + centerizeX,gear.Position.X.Offset,gear.Position.Y.Scale + centerizeY,gear.Position.Y.Offset), - Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/4,true)]] - delay(0, - function() - gear:remove() - end) - - Spawn(function() - while backpackIsOpen() do wait(0.03) end - waitForChild(player, 'Backpack') - local allEmpty = true - for i = 1, #gearSlots do - if gearSlots[i] ~= 'empty' then - allEmpty = false - end - end - - if allEmpty then - if #player.Backpack:GetChildren() < 1 then - backpackButton.Visible = false - else - backpackButton.Position = UDim2.new(0.5, -60, 1, -44) - end - clBackground.Visible = false - end - end) - end -end - -function insertGear(gear, addToSlot) - local pos = nil - if not addToSlot then - for i = 1, #gearSlots do - if gearSlots[i] == "empty" then - pos = i - break - end - end - - if pos == 1 and gearSlots[1] ~= "empty" then gear:remove() return end -- we are currently full, can't add in - else - pos = addToSlot - -- push all gear down one slot - local start = 1 - for i = 1, #gearSlots do - if gearSlots[i] == "empty" then - start = i - break - end - end - for i = start, pos + 1, -1 do - gearSlots[i] = gearSlots[i - 1] - if i == 10 then - gearSlots[i].SlotNumber.Text = "0" - gearSlots[i].SlotNumberDownShadow.Text = "0" - gearSlots[i].SlotNumberUpShadow.Text = "0" - else - gearSlots[i].SlotNumber.Text = i - gearSlots[i].SlotNumberDownShadow.Text = i - gearSlots[i].SlotNumberUpShadow.Text = i - end - end - end - - gearSlots[pos] = gear - if pos ~= maxNumLoadoutItems then - if(type(tostring(pos)) == "string") then - local posString = tostring(pos) - gear.SlotNumber.Text = posString - gear.SlotNumberDownShadow.Text = posString - gear.SlotNumberUpShadow.Text = posString - end - else -- tenth gear doesn't follow mathematical pattern :( - gear.SlotNumber.Text = "0" - gear.SlotNumberDownShadow.Text = "0" - gear.SlotNumberUpShadow.Text = "0" - end - gear.Visible = true - - local con = nil - con = gear.Kill.Changed:connect(function(prop) kill(prop,con,gear) end) -end - - -function reorganizeLoadout(gear, inserting, equipped, addToSlot) - if inserting then -- add in gear - insertGear(gear, addToSlot) - else - removeGear(gear) - end - if gear ~= "empty" then gear.ZIndex = 1 end -end - -function checkToolAncestry(child,parent) - if child:FindFirstChild("RobloxBuildTool") then return end -- don't show roblox build tools - if child:IsA("Tool") or child:IsA("HopperBin") then - for i = 1, #gearSlots do - if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then - if parent == nil then - gearSlots[i].Kill.Value = true - return false - elseif child.Parent == player.Character then - gearSlots[i].Selected = true - return true - elseif child.Parent == player.Backpack then - if child:IsA("Tool") or child:IsA("HopperBin") then gearSlots[i].Selected = false end - return true - else - gearSlots[i].Kill.Value = true - return false - end - return true - end - end - end -end - -function removeAllEquippedGear(physGear) - local stuff = player.Character:GetChildren() - for i = 1, #stuff do - if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then - if stuff[i]:IsA("Tool") then stuff[i].Parent = player.Backpack end - if stuff[i]:IsA("HopperBin") then - stuff[i]:Disable() - end - end - end -end - -function hopperBinSwitcher(numKey, physGear) - if not physGear then return end - - physGear:ToggleSelect() - - if gearSlots[numKey] == "empty" then return end - - if not physGear.Active then - gearSlots[numKey].Selected = false - normalizeButton(gearSlots[numKey]) - else - gearSlots[numKey].Selected = true - enlargeButton(gearSlots[numKey]) - end -end - -function toolSwitcher(numKey) - - if not gearSlots[numKey] then return end - local physGear = gearSlots[numKey].GearReference.Value - if physGear == nil then return end - - removeAllEquippedGear(physGear) -- we don't remove this gear, as then we get a double switcheroo - - local key = numKey - if numKey == 0 then key = 10 end - - for i = 1, #gearSlots do - if gearSlots[i] and gearSlots[i] ~= "empty" and i ~= key then - normalizeButton(gearSlots[i]) - gearSlots[i].Selected = false - if gearSlots[i].GearReference and gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value:IsA("HopperBin") and gearSlots[i].GearReference.Value.Active then - gearSlots[i].GearReference.Value:ToggleSelect() - end - end - end - - if physGear:IsA("HopperBin") then - hopperBinSwitcher(numKey,physGear) - else - if physGear.Parent == player.Character then - physGear.Parent = player.Backpack - - if gearSlots[numKey] ~= "empty" then - gearSlots[numKey].Selected = false - normalizeButton(gearSlots[numKey]) - end - else - --player.Character.Humanoid:EquipTool(physGear) - - physGear.Parent = player.Character - gearSlots[numKey].Selected = true - - enlargeButton(gearSlots[numKey]) - end - end -end - - -function activateGear(num) - local numKey = nil - if num == "0" then - numKey = 10 -- why do lua indexes have to start at 1? :( - else - numKey = tonumber(num) - end - - if(numKey == nil) then return end - - if gearSlots[numKey] ~= "empty" then - toolSwitcher(numKey) - end -end - - -enlargeButton = function(button) - if button.Size.Y.Scale > 1 then return end - if not button.Parent then return end - if not button.Selected then return end - - for i = 1, #gearSlots do - if gearSlots[i] == "empty" then break end - if gearSlots[i] ~= button then - normalizeButton(gearSlots[i]) - end - end - - if not enlargeOverride then - return - end - - if button:FindFirstChild('Highlight') then - button.Highlight.Visible = true - end - - if button:IsA("ImageButton") or button:IsA("TextButton") then - button.ZIndex = 5 - local centerizeX = -(buttonSizeEnlarge.X.Scale - button.Size.X.Scale)/2 - local centerizeY = -(buttonSizeEnlarge.Y.Scale - button.Size.Y.Scale)/2 - button:TweenSizeAndPosition(buttonSizeEnlarge, - UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset), - Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/5,enlargeOverride) - end -end - -normalizeAllButtons = function() - for i = 1, #gearSlots do - if gearSlots[i] == "empty" then break end - if gearSlots[i] ~= button then - normalizeButton(gearSlots[i],0.1) - end - end -end - - -normalizeButton = function(button, speed) - if not button then return end - if button.Size.Y.Scale <= 1 then return end - if button.Selected then return end - if not button.Parent then return end - - local moveSpeed = speed - if moveSpeed == nil or type(moveSpeed) ~= "number" then moveSpeed = guiTweenSpeed/5 end - - if button:FindFirstChild('Highlight') then - button.Highlight.Visible = false - end - - if button:IsA("ImageButton") or button:IsA("TextButton") then - button.ZIndex = 1 - local inverseEnlarge = 1/enlargeFactor - local centerizeX = -(buttonSizeNormal.X.Scale - button.Size.X.Scale)/2 - local centerizeY = -(buttonSizeNormal.Y.Scale - button.Size.Y.Scale)/2 - button:TweenSizeAndPosition(buttonSizeNormal, - UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset), - Enum.EasingDirection.Out, Enum.EasingStyle.Quad,moveSpeed,enlargeOverride) - end -end - -local waitForDebounce = function() - while debounce do - wait() - end -end - -function pointInRectangle(point,rectTopLeft,rectSize) - if point.x > rectTopLeft.x and point.x < (rectTopLeft.x + rectSize.x) then - if point.y > rectTopLeft.y and point.y < (rectTopLeft.y + rectSize.y) then - return true - end - end - return false -end - -function swapGear(gearClone,toFrame) - local toFrameChildren = toFrame:GetChildren() - if #toFrameChildren == 1 then - if toFrameChildren[1]:FindFirstChild("SlotNumber") then - - local toSlot = tonumber(toFrameChildren[1].SlotNumber.Text) - local gearCloneSlot = tonumber(gearClone.SlotNumber.Text) - if toSlot == 0 then toSlot = 10 end - if gearCloneSlot == 0 then gearCloneSlot = 10 end - - gearSlots[toSlot] = gearClone - gearSlots[gearCloneSlot] = toFrameChildren[1] - - toFrameChildren[1].SlotNumber.Text = gearClone.SlotNumber.Text - toFrameChildren[1].SlotNumberDownShadow.Text = gearClone.SlotNumber.Text - toFrameChildren[1].SlotNumberUpShadow.Text = gearClone.SlotNumber.Text - - local subString = string.sub(toFrame.Name,5) - gearClone.SlotNumber.Text = subString - gearClone.SlotNumberDownShadow.Text = subString - gearClone.SlotNumberUpShadow.Text = subString - - gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0) - toFrameChildren[1].Position = UDim2.new(toFrameChildren[1].Position.X.Scale,0,toFrameChildren[1].Position.Y.Scale,0) - - toFrameChildren[1].Parent = gearClone.Parent - gearClone.Parent = toFrame - end - else - local slotNum = tonumber(gearClone.SlotNumber.Text) - if slotNum == 0 then slotNum = 10 end - gearSlots[slotNum] = "empty" -- reset this gear slot - - local subString = string.sub(toFrame.Name,5) - gearClone.SlotNumber.Text = subString - gearClone.SlotNumberDownShadow.Text = subString - gearClone.SlotNumberUpShadow.Text = subString - - local toSlotNum = tonumber(gearClone.SlotNumber.Text) - if toSlotNum == 0 then toSlotNum = 10 end - gearSlots[toSlotNum] = gearClone - gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0) - gearClone.Parent = toFrame - end -end - -function resolveDrag(gearClone,x,y) - local mousePoint = Vector2.new(x,y) - - local frame = gearClone.Parent - local frames = frame.Parent:GetChildren() - - for i = 1, #frames do - if frames[i]:IsA("Frame") then - if pointInRectangle(mousePoint, frames[i].AbsolutePosition,frames[i].AbsoluteSize) then - swapGear(gearClone,frames[i]) - return true - end - end - end - - if x < frame.AbsolutePosition.x or x > ( frame.AbsolutePosition.x + frame.AbsoluteSize.x ) then - reorganizeLoadout(gearClone,false) - return false - elseif y < frame.AbsolutePosition.y or y > ( frame.AbsolutePosition.y + frame.AbsoluteSize.y ) then - reorganizeLoadout(gearClone,false) - return false - else - if dragBeginPos then gearClone.Position = dragBeginPos end - return -1 - end -end - -function unequipAllItems(dontEquipThis) - for i = 1, #gearSlots do - if gearSlots[i] == "empty" then break end - if gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value ~= dontEquipThis then - if gearSlots[i].GearReference.Value:IsA("HopperBin") then - gearSlots[i].GearReference.Value:Disable() - elseif gearSlots[i].GearReference.Value:IsA("Tool") then - gearSlots[i].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack - end - gearSlots[i].Selected = false - end - end -end - -function showToolTip(button, tip) - if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") and not IsTouchDevice() then - button.ToolTipLabel.Text = tostring(tip) - local xSize = button.ToolTipLabel.TextBounds.X + 6 - button.ToolTipLabel.Size = UDim2.new(0,xSize,0,20) - button.ToolTipLabel.Position = UDim2.new(0.5,-xSize/2,0,-30) - button.ToolTipLabel.Visible = true - end -end - -function hideToolTip(button, tip) - if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then - button.ToolTipLabel.Visible = false - end -end - -local addingPlayerChild = function(child, equipped, addToSlot, inventoryGearButton) - waitForDebounce() - debounce = true - - if child:FindFirstChild("RobloxBuildTool") then debounce = false return end -- don't show roblox build tools - if not child:IsA("Tool") then - if not child:IsA("HopperBin") then - debounce = false - return -- we don't care about anything besides tools (sigh...) - end - end - - if not addToSlot then - for i = 1, #gearSlots do - if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then -- we already have gear, do nothing - debounce = false - return - end - end - end - - local gearClone = currentLoadout.TempSlot:clone() - gearClone.Name = child.Name - gearClone.GearImage.Image = child.TextureId - if gearClone.GearImage.Image == "" then - gearClone.GearText.Text = child.Name - end - gearClone.GearReference.Value = child - - gearClone.MouseEnter:connect(function() - if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then - showToolTip(gearClone, gearClone.GearReference.Value.ToolTip) - end - end) - - gearClone.MouseLeave:connect(function() - if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then - hideToolTip(gearClone, gearClone.GearReference.Value.ToolTip) - end - end) - - gearClone.RobloxLocked = true - - local slotToMod = -1 - - if not addToSlot then - for i = 1, #gearSlots do - if gearSlots[i] == "empty" then - slotToMod = i - break - end - end - else - slotToMod = addToSlot - end - - if slotToMod == - 1 then -- No available slot to add in! - debounce = false - return - end - - local slotNum = slotToMod % 10 - local parent = currentLoadout:FindFirstChild("Slot"..tostring(slotNum)) - gearClone.Parent = parent - - if inventoryGearButton then - local absolutePositionFinal = inventoryGearButton.AbsolutePosition - local currentAbsolutePosition = gearClone.AbsolutePosition - local diff = absolutePositionFinal - currentAbsolutePosition - gearClone.Position = UDim2.new(gearClone.Position.X.Scale,diff.x,gearClone.Position.Y.Scale,diff.y) - gearClone.ZIndex = 4 - end - - if addToSlot then - reorganizeLoadout(gearClone, true, equipped, addToSlot) - else - reorganizeLoadout(gearClone, true) - end - - if gearClone.Parent == nil then debounce = false return end -- couldn't fit in (hopper is full!) - - if equipped then - gearClone.Selected = true - unequipAllItems(child) - delay(guiTweenSpeed + 0.01,function() -- if our gear is equipped, we will want to enlarge it when done moving - if gearClone:FindFirstChild("GearReference") and ( (gearClone.GearReference.Value:IsA("Tool") and gearClone.GearReference.Value.Parent == player.Character) or - (gearClone.GearReference.Value:IsA("HopperBin") and gearClone.GearReference.Value.Active == true) ) then - enlargeButton(gearClone) - end - end) - end - - local dragBeginPos = nil - local clickCon, buttonDeleteCon, mouseEnterCon, mouseLeaveCon, dragStop, dragBegin = nil - clickCon = gearClone.MouseButton1Click:connect(function() - if characterInWorkspace() then - if not gearClone.Draggable then - activateGear(gearClone.SlotNumber.Text) - end - end - end) - mouseEnterCon = gearClone.MouseEnter:connect(function() - if guiBackpack.Visible then - gearClone.Draggable = true - end - end) - dragBegin = gearClone.DragBegin:connect(function(pos) - dragBeginPos = pos - gearClone.ZIndex = 7 - local children = gearClone:GetChildren() - for i = 1, #children do - if children[i]:IsA("TextLabel") then - if string.find(children[i].Name,"Shadow") then - children[i].ZIndex = 8 - else - children[i].ZIndex = 9 - end - elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then - children[i].ZIndex = 7 - end - end - end) - dragStop = gearClone.DragStopped:connect(function(x,y) - if gearClone.Selected then - gearClone.ZIndex = 4 - else - gearClone.ZIndex = 3 - end - local children = gearClone:GetChildren() - for i = 1, #children do - if children[i]:IsA("TextLabel") then - if string.find(children[i].Name,"Shadow") then - children[i].ZIndex = 3 - else - children[i].ZIndex = 4 - end - elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then - children[i].ZIndex = 2 - end - end - resolveDrag(gearClone,x,y) - end) - mouseLeaveCon = gearClone.MouseLeave:connect(function() - gearClone.Draggable = false - end) - buttonDeleteCon = gearClone.AncestryChanged:connect(function() - if gearClone.Parent and gearClone.Parent.Parent == currentLoadout then return end - if clickCon then clickCon:disconnect() end - if buttonDeleteCon then buttonDeleteCon:disconnect() end - if mouseEnterCon then mouseEnterCon:disconnect() end - if mouseLeaveCon then mouseLeaveCon:disconnect() end - if dragStop then dragStop:disconnect() end - if dragBegin then dragBegin:disconnect() end - end) -- this probably isn't necessary since objects are being deleted (probably), but this might still leak just in case - - local childCon = nil - local childChangeCon = nil - childCon = child.AncestryChanged:connect(function(newChild,parent) - if not checkToolAncestry(newChild,parent) then - if childCon then childCon:disconnect() end - if childChangeCon then childChangeCon:disconnect() end - removeFromInventory(child) - elseif parent == game.Players.LocalPlayer.Backpack then - normalizeButton(gearClone) - end - end) - - childChangeCon = child.Changed:connect(function(prop) - if prop == "Name" then - if gearClone and gearClone.GearImage.Image == "" then - gearClone.GearText.Text = child.Name - end - elseif prop == "Active" then - if child and child:IsA("HopperBin") then - if not child.Active then - gearClone.Selected = false - normalizeButton(gearClone) - end - end - elseif prop == "TextureId" then - gearClone.GearImage.Image = child.TextureId - end - end) - - debounce = false - - Spawn(function() - while backpackIsOpen() do wait(0.03) end - for i = 1, #gearSlots do - if gearSlots[i] ~= 'empty' then - backpackButton.Position = UDim2.new(0.5, -60, 1, -108) - backpackButton.Visible = true - clBackground.Visible = true - end - end - end) -end - -function addToInventory(child) - if not child:IsA("Tool") or not child:IsA("HopperBin") then return end - - local slot = nil - for i = 1, #inventory do - if inventory[i] and inventory[i] == child then return end - if not inventory[i] then slot = i end - end - if slot then - inventory[slot] = child - elseif #inventory < 1 then - inventory[1] = child - else - inventory[#inventory + 1] = child - end -end - -function removeFromInventory(child) - for i = 1, #inventory do - if inventory[i] == child then - table.remove(inventory,i) - inventory[i] = nil - end - end -end - -local spreadOutGear = function() - loadoutChildren = currentLoadout:GetChildren() - - for i = 1, #loadoutChildren do - if loadoutChildren[i]:IsA("Frame") then - loadoutChildren[i].BackgroundTransparency = 0.5 - local slot = tonumber(string.sub(loadoutChildren[i].Name,5)) - if slot == 0 then slot = 10 end - if robloxGui.AbsoluteSize.Y <= 320 then - loadoutChildren[i]:TweenPosition(UDim2.new(0,(slot-1) * 60,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) - else - loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) - end - end - end -end - -local centerGear = function() - backpackWasOpened = true - loadoutChildren = currentLoadout:GetChildren() - local gearButtons = {} - local lastSlotAdd = nil - - for i = 1, #loadoutChildren do - if loadoutChildren[i]:IsA("Frame") then - if #loadoutChildren[i]:GetChildren() > 0 then - if loadoutChildren[i].Name == "Slot0" then - lastSlotAdd = loadoutChildren[i] - else - table.insert(gearButtons, loadoutChildren[i]) - end - end - loadoutChildren[i].BackgroundTransparency = 1 - end - end - if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end - - local startPos = ( 1 - (#gearButtons * 0.1) ) / 2 - for i = 1, #gearButtons do - if robloxGui.AbsoluteSize.Y <= 320 then - startPos = ( 0.5 - (#gearButtons * 0.333)/2 ) - gearButtons[i]:TweenPosition(UDim2.new(startPos + (i-1) * 0.33, 0, 0, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) - else - gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true) - end - end -end - -function editLoadout() - if inGearTab then - spreadOutGear() - end -end - -function readonlyLoadout() - if not inGearTab then - centerGear() - end -end - -function setupBackpackListener() - if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end - backpackChildCon = player.Backpack.ChildAdded:connect(function(child) - if not firstInstanceOfLoadout then - firstInstanceOfLoadout = true - backpackButton.Visible = true - clBackground.Visible = true - end - addingPlayerChild(child) - addToInventory(child) - end) -end - -function playerCharacterChildAdded(child) - addingPlayerChild(child,true) - addToInventory(child) -end - -function activateLoadout() - currentLoadout.Visible = true -end - -function deactivateLoadout() - currentLoadout.Visible = false -end - -function tabHandler(inFocus) - inGearTab = inFocus - if inFocus then - editLoadout() - else - readonlyLoadout() - end -end - --- NOTE: Nuke once event based system works 100% cases -local function handlePhoneLag() - for i = 1, 45 do - if i < 25 or not backpackWasOpened then - if robloxGui.AbsoluteSize.Y <= 320 then - local cChildren = currentLoadout:GetChildren() - for i = 1, #cChildren do - local slotNum = tonumber(string.sub(cChildren[i].Name, 5, string.len(cChildren[i].Name))) - if type(slotNum) == 'number' then - cChildren[i].Position = UDim2.new(0, (slotNum-1) * 60, 0, 0) - cChildren[i].BackgroundTransparency = 1.0 - end - end - end - end - wait(0.25) - end -end --- End Functions - --- Begin Script -wait() -- let stuff initialize incase this is first heartbeat... - -waitForChild(player,"Backpack") -waitForProperty(player,"Character") - --- not sure why this had no delay but the player.CharacterAdded one had one... this type of error would be easier to avoid with function reusage -delay(1,function() - local backpackChildren = player.Backpack:GetChildren() - local size = math.min(10,#backpackChildren) - for i = 1, size do - backpackButton.Visible = true - clBackground.Visible = true - addingPlayerChild(backpackChildren[i],false) - end - setupBackpackListener() -end) - --- NOTE: This is terrible. Event based system seems to fail almost 30% cases --- So using polling here. Consider this as an intermediate alternative. -delay(0, handlePhoneLag) - -player.ChildAdded:connect(function(child) - if child:IsA('PlayerGui') then - moveHealthBar(child) - end -end) - -waitForProperty(player,"Character") -for i,v in ipairs(player.Character:GetChildren()) do - playerCharacterChildAdded(v) -end -characterChildAddedCon = player.Character.ChildAdded:connect(function(child) playerCharacterChildAdded(child) end) - -waitForChild(player.Character,"Humanoid") -humanoidDiedCon = player.Character.Humanoid.Died:connect(function() - if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end - deactivateLoadout() - if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end -end) - -player.CharacterRemoving:connect(function() - for i = 1, #gearSlots do - if gearSlots[i] ~= "empty" then - gearSlots[i].Parent = nil - gearSlots[i] = "empty" - end - end -end) - -player.CharacterAdded:connect(function() - backpackWasOpened = false - waitForProperty(game.Players,"LocalPlayer") - player = game.Players.LocalPlayer -- make sure we are still looking at the correct character - waitForChild(player,"Backpack") - - - delay(1,function() - local backpackChildren = player.Backpack:GetChildren() - local size = math.min(10,#backpackChildren) - for i = 1, size do - backpackButton.Visible = true - clBackground.Visible = true - addingPlayerChild(backpackChildren[i],false) - end - setupBackpackListener() - end) - - activateLoadout() - - if characterChildAddedCon then - characterChildAddedCon:disconnect() - characterChildAddedCon = nil - end - - characterChildAddedCon = - player.Character.ChildAdded:connect(function(child) - addingPlayerChild(child,true) - end) - - waitForChild(player.Character,"Humanoid") - if backpack.Visible then - backpackOpenEvent:Fire() - end - humanoidDiedCon = - player.Character.Humanoid.Died:connect(function() - backpackButton.Visible = false - clBackground.Visible = false - firstInstanceOfLoadout = false - deactivateLoadout() - - if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end - if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end - end) - waitForChild(player, 'PlayerGui') - moveHealthBar(player.PlayerGui) - delay(0, handlePhoneLag) - -end) - -waitForChild(guiBackpack,"SwapSlot") -guiBackpack.SwapSlot.Changed:connect(function() - if guiBackpack.SwapSlot.Value then - local swapSlot = guiBackpack.SwapSlot - local pos = swapSlot.Slot.Value - if pos == 0 then pos = 10 end - if gearSlots[pos] then - reorganizeLoadout(gearSlots[pos],false) - end - if swapSlot.GearButton.Value then - addingPlayerChild(swapSlot.GearButton.Value.GearReference.Value,false,pos) - end - guiBackpack.SwapSlot.Value = false - end -end) - -game:GetService("GuiService").KeyPressed:connect(function(key) - if characterInWorkspace() then - activateGear(key) - end -end) - -backpackOpenEvent.Event:connect(editLoadout) -backpackCloseEvent.Event:connect(centerGear) -tabClickedEvent.Event:connect(function ( tabName ) - tabHandler(tabName == StaticTabName) -end) \ No newline at end of file +%15% +-- A couple of necessary functions +print("BackpackWardrobe.lua loaded - edit 14") + +local function waitForChild(instance, name) + assert(instance) + assert(name) + while not instance:FindFirstChild(name) do + instance.ChildAdded:wait() + end + return instance:FindFirstChild(name) +end +local function waitForProperty(instance, property) + assert(instance) + assert(property) + while not instance[property] do + instance.Changed:wait() + end +end + +waitForChild(game,"Players") +waitForProperty(game.Players,"LocalPlayer") +local player = game.Players.LocalPlayer + +local RbxGui, msg = LoadLibrary("RbxGui") +if not RbxGui then print("could not find RbxGui!") return end + +--- Begin Locals +local StaticTabName = "wardrobe" + +local backpack = script.Parent +local screen = script.Parent.Parent + +local backpackItems = {} +local buttons = {} + +local debounce = false +local browsingMenu = false + +local mouseEnterCons = {} +local mouseClickCons = {} + +local characterChildAddedCon = nil +local characterChildRemovedCon = nil +local backpackAddCon = nil + +local Camera = game.Workspace.CurrentCamera + +local playerBackpack = waitForChild(player,"Backpack") + +waitForChild(backpack,"Tabs") + +waitForChild(backpack,"Wardrobe") + +local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout") + +local walkSpeed = 16 +local screenSize = game:GetService("CoreGui"):FindFirstChild("RobloxGui").AbsoluteSize +local rotateCharacter = false +local rotateCharacterButton = waitForChild(backpack.Wardrobe,"PreviewButton") + +local swapSlot = waitForChild(script.Parent,"SwapSlot") + +local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager") +local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent") +local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent") +local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent") +local resizeEvent = waitForChild(backpackManager,"ResizeEvent") +local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent") +local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady") + +-- creating scroll bar early as to make sure items get placed correctly + + +-- Begin Functions +function lerpTest(from, to) + local ax, ay, az, a11, a12, a13, a21, a22, a23, a31, a32, a33 = from:components() + local bx, by, bz, b11, b12, b13, b21, b22, b23, b31, b32, b33 = to:components() + + local diffx = bx - ax; + local diffy = by - ay; + local diffz = bz - az; + + local diff11 = b11 - a11; + local diff12 = b12 - a12; + local diff13 = b13 - a13; + + local diff21 = b21 - a21; + local diff22 = b22 - a22; + local diff23 = b23 - a23; + + local diff31 = b31 - a31; + local diff32 = b32 - a32; + local diff33 = b33 - a33; + + while wait(0.1) do + break + end +end + +function removeFromMap(map,object) + for i = 1, #map do + if map[i] == object then + table.remove(map,i) + break + end + end +end + +function robloxLock(instance) + instance.RobloxLocked = true + children = instance:GetChildren() + if children then + for i, child in ipairs(children) do + robloxLock(child) + end + end +end + +function buttonClick(button) + if button:FindFirstChild("UnequipContextMenu") and not button.Active then + button.UnequipContextMenu.Visible = true + browsingMenu = true + end +end + +function tabClickHandler(tabName) + if tabName == StaticTabName then + backpackOpenHandler(tabName) + else + backpackCloseHandler(tabName) + end +end + +function backpackOpenHandler(currentTab) + if currentTab and currentTab ~= StaticTabName then + backpack.Wardrobe.Visible = false + return + end + + backpack.Wardrobe.Visible = true + createView() + tellBackpackReadyFunc:Invoke() +end + +function backpackCloseHandler(currentTab) + if currentTab and currentTab ~= StaticTabName then + backpack.Wardrobe.Visible = false + revertView() + return + end + + backpack.Wardrobe.Visible = false + revertView() + tellBackpackReadyFunc:Invoke() +end + +function highlight(button) + button.TextColor3 = Color3.new(0,0,0) + button.BackgroundColor3 = Color3.new(0.8,0.8,0.8) +end +function clearHighlight(button) + button.TextColor3 = Color3.new(1,1,1) + button.BackgroundColor3 = Color3.new(0,0,0) +end + +function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +function splitByWhitespace(text) + if type(text) ~= "string" then return nil end + + local terms = {} + for token in string.gmatch(text, "[^%s]+") do + if string.len(token) > 0 then + table.insert(terms,token) + end + end + return terms +end + +function createView() + -- stop player from moving and store initial speed (they can still jump though) + if player.Character.Humanoid.WalkSpeed ~= 0 then walkSpeed = player.Character.Humanoid.WalkSpeed end + player.Character.Humanoid.WalkSpeed = 0 + + -- initialize camera + Camera.CameraType = Enum.CameraType.Scriptable + focusCamera() +end + +function revertView() + -- restore initial walk speed + player.Character.Humanoid.WalkSpeed = walkSpeed + + -- restore player camera + Camera.CameraType = Enum.CameraType.Custom + + -- if character spin is enabled then disable it + if rotateCharacter then toggleCharacterSpin() end +end + +function focusCamera() + if not backpack.Wardrobe.Visible then return end + + local cameraAngle = CFrame.fromEulerAnglesXYZ(0, math.pi, 0) * CFrame.fromEulerAnglesXYZ(0, -0.1, 0) + local cameraPosition = CFrame.new(screenSize.X*0.00983455882, 0, screenSize.Y*-0.01527777777) + + Camera.CoordinateFrame = game.Players.LocalPlayer.Character.Torso.CFrame * cameraPosition * cameraAngle +end + +function toggleCharacterSpin() + rotateCharacter = not rotateCharacter + + if rotateCharacter then + rotateCharacterButton.Text = "Pause" + else + rotateCharacterButton.Text = "Rotate" + end + + while rotateCharacter do + wait(0.05) + player.Character.Torso.CFrame = player.Character.Torso.CFrame * CFrame.Angles(0,0.035,0) + end +end + +------------------------- Start Lifelong Connections ----------------------- + + +resizeEvent.Event:connect(function(absSize) + if debounce then return end + + debounce = true + wait() + screenSize = absSize + focusCamera() + debounce = false +end) + + +------------------------- End Lifelong Connections ----------------------- + +backpackOpenEvent.Event:connect(backpackOpenHandler) +backpackCloseEvent.Event:connect(backpackCloseHandler) +tabClickedEvent.Event:connect(tabClickHandler) +rotateCharacterButton.MouseButton1Click:connect(toggleCharacterSpin) \ No newline at end of file