· 9 years ago · Nov 08, 2016, 12:08 AM
1game:GetService("StarterGui"):SetCoreGuiEnabled("PlayerList", false) -- Ctrl+F "API DOCS" to get the docs
2
3--settings. Don't make these local.
4ALLOW_BC_ICONS = true -- Players' BC icons will be shown next to their names
5PRIMARY_LEADERSTATS_ENABLED = true -- Leaderstats will appear in large text under the player's name
6SHOW_PRIMARY_LEADERSTAT_NAMES = true -- Primary leaderstats will have their names shown next to them
7
8
9HIDDEN_PLAYERS = {
10 mentos7 = false,
11 haloruisu = false
12}
13
14ADMINS =
15{
16 player1 = "http://www.roblox.com/asset/?id=211643318",
17}
18GroupID = {["TC"] = 1216443--[[TC]],["SL"] = 1216259--[[SL]],["MP"] = 1215350--[[MP]],["KA"] = 2719207--[[KA]],["SG"] = 1216268--[[SG]]}
19EmblemID = {["TC"] = "http://www.roblox.com/asset/?id=197351988"--[[TC]],["SL"] = "http://www.roblox.com/asset/?id=197352057"--[[SL]],["MP"] = "http://www.roblox.com/asset/?id=197351966"--[[MP]],["KA"] = "http://www.roblox.com/asset?id=540195803"--[[KA]],["SG"] = "http://www.roblox.com/asset/?id=197352012"--[[SG]]}
20
21
22
23ADMIN_ICON_WIDTHS = {
24 player1 = 30,
25}
26
27ALIASES = {
28 player1 = "Mentos",
29 haloruisu = "Ruisu"
30-- mentos7 = "Yuki",
31--= haloruisu = "Ruisu",
32
33}
34
35-- API DOCS
36-- _G.PlayerListAPI:SetAllowBCIcons(true or false)
37-- :AddAdmin(String name, Optional Content customIcon, Optional Int customIconWidth)
38-- :RemoveAdmin(String name)
39-- :SetAlias(String name, String alias)
40-- :SetPlayerIsHidden(String name)
41-- _G.ChatAPI:SendChat(String playername, String message, Color3 customcolor)
42
43for name,a in pairs(ADMINS) do
44 ADMINS[name:lower()] = a
45end
46for name,a in pairs(ALIASES) do
47 ALIASES[name:lower()] = a
48end
49for name,a in pairs(HIDDEN_PLAYERS) do
50 HIDDEN_PLAYERS[name:lower()] = a
51end
52
53function GetAliasOf(name)
54 return ALIASES[name:lower()] or name
55end
56
57local export = {}
58
59export.SetAllowBCIcons = function(self, b)
60 ALLOW_BC_ICONS = b
61end
62
63export.AddAdmin = function(self, name, customicon, customiconwidth)
64 ADMINS[name:lower()] = customicon or 1
65 ADMIN_ICON_WIDTHS[name:lower()] = customiconwidth or 16
66end
67
68export.RemoveAdmin = function(self, name)
69 ADMINS[name:lower()] = 0
70end
71
72
73export.SetAlias = function(self, name, alias)
74 if alias == "" or alias == nil then
75 ALIASES[name:lower()] = name
76 else
77 ALIASES[name:lower()] = alias
78 end
79end
80
81export.GetAlias = function(self, name)
82 return GetAliasOf(name)
83end
84
85export.SetPlayerIsHidden = function(self, name, bool)
86 local current = not not HIDDEN_PLAYERS[name:lower()]
87 local new = not not bool
88 local changing = current ~= new
89
90 HIDDEN_PLAYERS[name:lower()] = new
91
92 if changing then
93 if new then
94 local existingPlayer = nil
95
96 for index, player in next, game.Players:GetPlayers() do
97 if player.Name:lower() == name:lower() then
98 existingPlayer = player
99 break
100 end
101 end
102
103
104 if existingPlayer ~= nil then
105 InsertPlayerFrame(existingPlayer)
106 end
107 elseif not new then
108 local existingPlayer = nil
109
110 for index, player in next, game.Players:GetPlayers() do
111 if player.Name:lower() == name:lower() then
112 existingPlayer = player
113 break
114 end
115 end
116
117
118 if existingPlayer ~= nil then
119 RemovePlayerFrame(existingPlayer)
120 end
121 end
122 end
123end
124
125_G.PlayerListAPI = export
126
127local Images = {
128 bottomDark = '94691904',
129 bottomLight = '94691940',
130 midDark = '94691980',
131 midLight = '94692025',
132 LargeDark = '96098866',
133 LargeLight = '96098920',
134 LargeHeader = '96097470',
135 NormalHeader = '94692054',
136 LargeBottom = '96397271',
137 NormalBottom = '',
138 DarkBluePopupMid = '97114905',
139 LightBluePopupMid = '97114905',
140 DarkPopupMid = '97112126',
141 LightPopupMid = '97109338',
142 DarkBluePopupTop = '97114838',
143 DarkBluePopupBottom = '97114758',
144 DarkPopupBottom = '100869219',
145 LightPopupBottom = '97109175',
146}
147
148local BASE_TWEEN = .25
149
150local MOUSE_HOLD_TIME = .15
151local MOUSE_DRAG_DISTANCE = 15
152
153--[[
154 Generic object Create function, which I am using to create Gui's
155 Thanks to Stravant!
156--]]
157local Obj = {}
158function Obj.Create(guiType)
159 return function(data)
160 local obj = Instance.new(guiType)
161 for k, v in pairs(data) do
162 if type(k) == 'number' then
163 v.Parent = obj
164 else
165 obj[k] = v
166 end
167 end
168 return obj
169 end
170end
171
172--[[
173 makes a full sized background for a guiobject
174 @Args:
175 imgName asset name of image to fill background
176 @Return: background gui object
177--]]
178function MakeBackgroundGuiObj(imgName)
179 return Obj.Create'ImageLabel'
180 {
181 Name = 'Background',
182 BackgroundTransparency = 1,
183 Image = imgName,
184 Position = UDim2.new(0, 0, 0, 0),
185 Size = UDim2.new(1,0,1,0),
186 }
187end
188--[[ turns 255 integer color value to a color3 --]]
189function Color3I(r,g,b)
190 return Color3.new(r/255,g/255,b/255)
191end
192
193--[[
194 Gets correct icon for builder's club status to display by name
195 @Args:
196 membershipType Enum of membership status
197 @Return: string of image asset
198--]]
199function getMembershipTypeIcon(membershipType,playerName)
200 if game.Players[playerName]:IsInGroup(GroupID["KA"]) then
201 return EmblemID["KA"]
202 elseif game.Players[playerName]:IsInGroup(GroupID["SL"]) then
203 return EmblemID["SL"]
204 elseif game.Players[playerName]:IsInGroup(GroupID["MP"]) then
205 return EmblemID["MP"]
206 elseif game.Players[playerName]:IsInGroup(GroupID["SG"]) then
207 return EmblemID["SG"]
208 elseif game.Players[playerName]:IsInGroup(GroupID["TC"]) then
209 return EmblemID["TC"]
210 end
211 if ADMINS[string.lower(playerName)]~=nil then
212 return ADMINS[string.lower(playerName)]
213 else
214 error("Unknown membershipType" .. membershipType)
215 end
216end
217local function getFriendStatusIcon(friendStatus)
218 if friendStatus == Enum.FriendStatus.Unknown or friendStatus == Enum.FriendStatus.NotFriend then
219 return ""
220 elseif friendStatus == Enum.FriendStatus.Friend then
221 return "http://www.roblox.com/asset/?id=99749771"
222 elseif friendStatus == Enum.FriendStatus.FriendRequestSent then
223 return "http://www.roblox.com/asset/?id=99776888"
224 elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then
225 return "http://www.roblox.com/asset/?id=99776838"
226 else
227 error("Unknown FriendStatus: " .. friendStatus)
228 end
229end
230
231
232--[[
233 Utility function to create buttons for the popup menus
234 @Args:
235 nparent what to parent this button to
236 ntext text to put on this button
237 index number index of this entry in menu
238 last is this the last element of the popup menu
239 @Return: a popup menu button
240--]]
241function MakePopupButton(nparent,ntext,index,last)
242 local tobj = Obj.Create"ImageButton"
243 {
244 Name = 'ReportButton',
245 BackgroundTransparency = 1,
246 Position = UDim2.new(0,0,1*index,0),
247 Size = UDim2.new(1, 0, 1, 0),
248 ZIndex=7,
249 Obj.Create'TextLabel'
250 {
251 Name = 'ButtonText',
252 BackgroundTransparency = 1,
253 Position = UDim2.new(.07, 0, .07, 0),
254 Size = UDim2.new(.86,0,.86,0),
255 Parent = HeaderFrame,
256 Font = 'ArialBold',
257 Text = ntext,
258 FontSize = 'Size14',
259 TextScaled = true,
260 TextColor3 = Color3.new(1,1,1),
261 TextStrokeTransparency = 1,
262 ZIndex=7,
263 },
264 Parent = nparent,
265 }
266 if index==0 then
267 tobj.Image = 'http://www.roblox.com/asset/?id=97108784'
268 elseif last then
269 if index%2==1 then
270 tobj.Image = 'http://www.roblox.com/asset/?id='.. Images['LightPopupBottom']
271 else
272 tobj.Image = 'http://www.roblox.com/asset/?id='.. Images['DarkPopupBottom']
273 end
274 else
275 if index%2==1 then
276 tobj.Image = 'http://www.roblox.com/asset/?id=97112126'
277 else
278 tobj.Image = 'http://www.roblox.com/asset/?id=97109338'
279 end
280 end
281 return tobj
282end
283
284
285--[[
286 obligatory wait for child function
287 @Args:
288 parent Parent object to look for child in
289 child name of child object to look for
290 @Return: object waited for
291--]]
292function WaitForChild(parent,child)
293 while not parent:FindFirstChild(child) do
294 wait() debugprint(" child "..parent.Name.." waiting for "..child)
295 end
296 return parent[child]
297end
298
299 ---------------------------
300 -- Workspace Objects
301 ---------------------------
302
303-- might want to move all this to an init function, wait for localplayer elsewhere
304local Players = game:GetService('Players')
305-- make sure this doesn't run on the server(it will if you dont do this)
306while not Players.LocalPlayer do
307 Players.Changed:wait()
308end
309
310local LocalPlayer = Players.LocalPlayer
311local Mouse = LocalPlayer:GetMouse()
312
313local ScreenGui =script.Parent.PlayerListScreen
314local MainFrame = script.Parent.PlayerListScreen.LeaderBoardFrame
315local FocusFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.FocusFrame
316--frame used for expanding leaderstats when frame is 'focused'
317
318local TemplateFrameYSize = 0.670000017
319
320 -- HEADER
321local HeaderFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.Header
322
323 local HeaderFrameHeight = HeaderFrame.Size.Y.Scale
324 local MaximizeButton = script.Parent.PlayerListScreen.LeaderBoardFrame.Header.MaximizeButton
325
326 local HeaderName = script.Parent.PlayerListScreen.LeaderBoardFrame.Header.PlayerName
327 local HeaderScore = script.Parent.PlayerListScreen.LeaderBoardFrame.Header.PlayerScore
328 local HeaderScoreName = script.Parent.PlayerListScreen.LeaderBoardFrame.Header.PlayerScore.ScoreNameLabel
329
330 HeaderName.Text = GetAliasOf(game.Players.LocalPlayer.Name)
331
332 -- BOTTOM
333 --used for shifting bottom frame for mouse over effects
334local BottomShiftFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.BottomShiftFrame
335local BottomFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.BottomShiftFrame.Bottom
336local ExtendButton = script.Parent.PlayerListScreen.LeaderBoardFrame.BottomShiftFrame.Bottom.bigbutton
337local ExtendTab = script.Parent.PlayerListScreen.LeaderBoardFrame.BottomShiftFrame.Bottom.extendTab
338local TopClipFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.ListFrame
339local BottomClipFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.ListFrame.BottomFrame
340local ScrollBarFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.ListFrame.BottomFrame.ScrollBarFrame
341local ScrollBar = script.Parent.PlayerListScreen.LeaderBoardFrame.ListFrame.BottomFrame.ScrollBarFrame.ScrollBar
342local ListFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.ListFrame.BottomFrame.SubFrame
343local PopUpClipFrame = script.Parent.PlayerListScreen.LeaderBoardFrame.PopUpFrame
344
345
346local PopUpPanel = nil
347 local PopUpPanelTemplate = Obj.Create"Frame"
348 {
349 Name = 'Panel',
350 BackgroundTransparency = 1,
351 Position = UDim2.new(1,0,0,0),
352 Size = UDim2.new(1,0,.032,0),
353 Parent = PopUpClipFrame,
354 }
355
356local StatTitles = Obj.Create"Frame"
357{
358 Name = 'StatTitles',
359 BackgroundTransparency = 1,
360 Position = UDim2.new(0,0,1,-10),
361 Size = UDim2.new(1, 0, 0, 0),
362 Parent = HeaderFrame,
363}
364
365local IsMinimized = Instance.new('BoolValue')
366local IsMaximized = Instance.new('BoolValue')
367local IsTabified = Instance.new('BoolValue')
368local AreNamesExpanded = Instance.new('BoolValue')
369
370
371local MiddleTemplate = Obj.Create"Frame"
372{
373 Name = 'MidTemplate',
374 BackgroundTransparency = 1,
375 Position = UDim2.new(100,0,.07,0),
376 Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0),
377 Obj.Create'ImageLabel'
378 {
379 Name = 'BCLabel',
380 Active = true,
381 BackgroundTransparency = 1,
382 Position = UDim2.new(.005, 5, .10, 0),
383 Size = UDim2.new(0,16,0,16),
384 SizeConstraint = 'RelativeYY',
385 Image = "",
386 ZIndex = 9,
387 },
388 Obj.Create'ImageLabel'
389 {
390 Name = 'FriendLabel',
391 Active = true,
392 BackgroundTransparency = 1,
393 Position = UDim2.new(.005, 5, .15, 0),
394 Size = UDim2.new(0,16,0,16),
395 SizeConstraint = 'RelativeYY',
396 Image = "",
397 ZIndex = 3,
398 },
399 Obj.Create"ImageButton"
400 {
401 Name = 'ClickListener',
402 Active = true,
403 BackgroundTransparency = 1,
404 Position = UDim2.new(.005, 1, 0, 0),
405 Size = UDim2.new(.96,0,1,0),
406 ZIndex = 3,
407 },
408 Obj.Create"Frame"
409 {
410 Name = 'TitleFrame',
411 BackgroundTransparency = 1,
412 Position = UDim2.new(.01, 0, 0, 0),
413 Size = UDim2.new(0,140,1,0),
414 ClipsDescendants=true,
415 Obj.Create"TextLabel"
416 {
417 Name = 'Title',
418 BackgroundTransparency = 1,
419 Position = UDim2.new(0, 5, 0, 0),
420 Size = UDim2.new(100,0,1,0),
421 Font = 'Arial',
422 FontSize='Size14',
423 TextColor3 = Color3.new(1,1,1),
424 TextXAlignment = 'Left',
425 TextYAlignment = 'Center',
426 ZIndex = 3,
427 },
428 },
429
430 Obj.Create"TextLabel"
431 {
432 Name = 'PlayerScore',
433 BackgroundTransparency = 1,
434 Position = UDim2.new(0, 0, 0, 0),
435 Size = UDim2.new(1,0,1,0),
436 Font = 'ArialBold',
437 Text = '',
438 FontSize='Size14',
439 TextColor3 = Color3.new(1,1,1),
440 TextXAlignment = 'Right',
441 TextYAlignment = 'Center',
442 ZIndex = 3,
443 },
444 --Obj.Create'IntValue'{Name = 'ID'},
445 --Obj.Create'ObjectValue'{Name = 'Player'},
446 --Obj.Create'IntValue'{Name = 'Score'},
447 ZIndex = 3,
448}
449local MiddleBGTemplate = Obj.Create"Frame"
450{
451 Name = 'MidBGTemplate',
452 BackgroundTransparency = .5,
453 Position = UDim2.new(100,0,.07,0),
454 Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0),
455 BackgroundColor3 = BrickColor.new("Deep orange").Color,
456 MakeBackgroundGuiObj(''),
457
458}
459
460 -- REPORT ABUSE OBJECTS
461
462local ReportAbuseShield = Obj.Create"TextButton"
463{
464 Name = "ReportAbuseShield",
465 Text = "",
466 AutoButtonColor = false,
467 Active = true,
468 Visible = true,
469 Size = UDim2.new(1,0,1,0),
470 BackgroundColor3 = Color3I(51,51,51),
471 BorderColor3 = Color3I(27,42,53),
472 BackgroundTransparency = 1,
473}
474
475local ReportAbuseFrame = Obj.Create "Frame"
476{
477 Name = "ReportAbuseFrame",
478 Position = UDim2.new(0.5, -250, 0.5, -100),
479 Size = UDim2.new(0, 500, 0, 200),
480 ZIndex = 9,
481 Parent = ReportAbuseShield,
482 Style = "RobloxRound"
483}
484
485local ReportAbuseClose = Obj.Create "TextButton"
486{
487 BackgroundColor3 = Color3.new(150/255, 0, 0),
488 BorderColor3 = Color3.new(200/255, 200/255, 200/255),
489 Name = "Close",
490 Position = UDim2.new(1, -20, 0, 0),
491 Size = UDim2.new(0, 20, 0, 20),
492 ZIndex = 10,
493 Font = "SourceSansBold",
494 FontSize = "Size12",
495 Text = "X",
496 TextColor3 = Color3.new(200/255, 200/255, 200/255),
497 TextStrokeTransparency = 0,
498 Parent = ReportAbuseFrame
499}
500
501local ReportAbuseHeader = Obj.Create "TextLabel"
502{
503 BackgroundTransparency = 1,
504 Name = "Sorry",
505 Position = UDim2.new(0.5, 0, 0, 20),
506 ZIndex = 10,
507 Font = "ArialBold",
508 FontSize = "Size36",
509 Text = "Sorry! :(",
510 TextColor3 = Color3.new(200/255, 200/255, 200/255),
511 TextStrokeTransparency = 0,
512 Parent = ReportAbuseFrame
513}
514
515local ReportAbuseInfo = Obj.Create "TextLabel"
516{
517 BackgroundColor3 = Color3.new(),
518 BackgroundTransparency = 0.5,
519 BorderColor3 = Color3.new(200/255, 200/255, 200/255),
520 Name = "ReportAbuseInfo",
521 Position = UDim2.new(0, 0, 0, 50),
522 Size = UDim2.new(1, 0, 1, -50),
523 Font = "ArialBold",
524 FontSize = "Size14",
525 Text = "This game is using a specialized player list that uses an API to unlock certain features. Because this is a modified player list, certain high-level functions are disabled such as in-game Friend Requests and the Report Abuse function.",
526 TextColor3 = Color3.new(200/255, 200/255, 200/255),
527 TextStrokeTransparency = 0,
528 TextYAlignment = "Top",
529 ZIndex = 10,
530 TextWrapped = true,
531 Parent = ReportAbuseFrame,
532 Obj.Create"TextLabel"
533 {
534 BackgroundTransparency = 1,
535 Name = "FRs",
536 Position = UDim2.new(0, 20, 0, 50),
537 Size = UDim2.new(1, -40, 1, -50),
538 ZIndex = 10,
539 Font = "Arial",
540 FontSize = "Size12",
541 Text = "To add a friend, you will need to go to the roblox site and find them using the player search page. Once you've found them, click the \"Add Friend\" button under their character.",
542 TextColor3 = Color3.new(200/255, 200/255, 200/255),
543 TextStrokeTransparency = 0,
544 TextWrapped = true,
545 TextYAlignment = "Top"
546 },
547 Obj.Create"TextLabel"
548 {
549 BackgroundTransparency = 1,
550 Name = "Report",
551 Position = UDim2.new(0, 20, 0, 90),
552 Size = UDim2.new(1, -40, 1, -50),
553 ZIndex = 10,
554 Font = "Arial",
555 FontSize = "Size12",
556 Text = "To report abuse, you need to open your game menu by pressing the 'Esc' button on your keyboard, then click Report Abuse and fill out the necessary information.",
557 TextColor3 = Color3.new(200/255, 200/255, 200/255),
558 TextStrokeTransparency = 0,
559 TextWrapped = true,
560 TextYAlignment = "Top"
561 }
562}
563
564local BigButton=Instance.new('ImageButton')
565 BigButton.Size=UDim2.new(1,0,1,0)
566 BigButton.BackgroundTransparency=1
567 BigButton.ZIndex=8
568 BigButton.Visible=false
569 --BigButton.Active=false
570 BigButton.Parent=ScreenGui
571
572
573 local debugFrame = Obj.Create"Frame"
574 {
575 Name = 'debugframe',
576 Position = UDim2.new(0, 0, 0, 0),
577 Size = UDim2.new(0, 150, 0, 800),--0.99000001
578 BackgroundTransparency = 1,
579
580 }
581 local debugplayers = Obj.Create"TextLabel"
582 {
583 BackgroundTransparency = .8,
584 Position = UDim2.new(0, 0, .01, 0),
585 Size = UDim2.new(1,0,.5,0),
586 Parent = debugFrame,
587 Font = 'ArialBold',
588 Text = '--',
589 FontSize='Size14',
590 TextWrapped=true,
591 TextColor3 = Color3.new(1,1,1),
592 TextStrokeColor3 = Color3.new(0,0,0),
593 TextStrokeTransparency = 0,
594 TextXAlignment = 'Right',
595 TextYAlignment = 'Center',
596 }
597 local debugOutput = Obj.Create"TextLabel"
598 {
599 BackgroundTransparency = .8,
600 Position = UDim2.new(0, 0, .5, 0),
601 Size = UDim2.new(1,0,.5,0),
602 Parent = debugFrame,
603 Font = 'ArialBold',
604 Text = '--',
605 FontSize='Size14',
606 TextWrapped=true,
607 TextColor3 = Color3.new(1,1,1),
608 TextStrokeColor3 = Color3.new(0,0,0),
609 TextStrokeTransparency = 0,
610 TextXAlignment = 'Right',
611 TextYAlignment = 'Center',
612 }
613
614
615--[[
616 simple function to toggle the display of debug output
617--]]
618local DebugPrintEnabled=true
619function debugprint(str)
620 --print(str)
621 if DebugPrintEnabled then
622 debugOutput.Text=str
623 end
624end
625
626
627 -------------------------
628 -- Script objects
629 -------------------------
630local RbxGui = assert(LoadLibrary('RbxGui'))
631
632 -- number of entries to show if you click minimize
633local DefaultEntriesOnScreen = 8
634
635
636
637
638
639for _,i in pairs(Images) do
640 Game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id="..i)
641end
642
643 -- ordered array of 'score data', each entry has:
644 -- Name(String)
645 -- Priority(number)
646 -- IsPrimary (bool, should it be shown in upper right)
647 -- MaxLength (integer, of the length of the longest element for this column)
648local ScoreNames = {}
649 -- prevents flipping in playerlist panels
650local AddId = 0
651 -- intermediate table form of all player entries in format of:
652 -- Frame
653 -- Player
654 -- Score
655 -- ID
656 -- MyTeam (team ENRTY(not actual team) I am currently on)
657local PlayerFrames = {}
658 -- intermediate ordered frame array, composed of Entrys of
659 -- Frame
660 -- MyTeam (my team object)
661 -- MyPlayers ( an ordered array of all player frames in team )
662 -- AutoHide (bool saying whether it should be hidden)
663 -- IsHidden (bool)
664 -- ID (int to prevent flipping out of leaderboard, fun times)
665local TeamFrames = {}
666 -- one special entry from teamFrames, for unaffiliated players, only shown if players non - empty
667local NeutralTeam = nil
668
669 -- final 'to be displayed' list of frames
670local MiddleFrames = {}
671local MiddleFrameBackgrounds = {}
672local MiddleFrameHeight = .03
673 -- time of last click
674local LastClick = 0
675local ButtonCooldown = .25
676
677local OnIos = false
678pcall(function() OnIos = Game:GetService('UserInputService').TouchEnabled end)
679
680
681 -- you get 200 of x screen space per stat added, start width 16%
682local BaseScreenXSize = 150
683local SpacingPerStat = 10 --spacing between stats
684
685
686local MaximizedBounds = UDim2.new(.5,0,1,0)
687local MaximizedPosition = UDim2.new(.25,0,0.149999961,0)
688local NormalBounds = UDim2.new(0,BaseScreenXSize, 0, 800)
689local NormalPosition = UDim2.new(1 , - BaseScreenXSize, 0.149999961, 0)
690
691local MinimizedBounds = UDim2.new(0, BaseScreenXSize, 0.99000001, 0)
692
693--free space to give last stat on the right
694local RightEdgeSpace = -.04
695
696 -- where the scroll par currently is positioned
697local ScrollPosition = 0.75999999
698local IsDragging = false -- am I dragging the player list
699
700local DefaultBottomClipPos = BottomClipFrame.Position.Y.Scale
701
702local LastSelectedPlayerEntry = nil
703local SelectedPlayerEntry = nil
704local SelectedPlayer = nil
705
706 -- locks(semaphores) for stopping race conditions
707local AddingFrameLock = false
708local ChangingOrderLock = false
709local AddingStatLock = false
710local BaseUpdateLock = false
711local WaitForClickLock = false
712local InPopupWaitForClick=false
713local PlayerChangedLock = false
714local NeutralTeamLock = false
715
716local ScrollWheelConnections = {}
717
718
719local DefaultListSize = 8
720if not OnIos then DefaultListSize = 12 end
721local DidMinimizeDrag = false
722
723--local PlaceCreatorId=game.CreatorId
724
725 -- report abuse objects
726local AbuseName
727local Abuses = {
728 "Bad Words or Threats",
729 "Bad Username",
730 "Talking about Dating",
731 "Account Trading or Sharing",
732 "Asking Personal Questions",
733 "Rude or Mean Behavior",
734 "False Reporting Me"
735}
736local UpdateAbuseFunction
737local AbuseDropDown, UpdateAbuseSelection
738
739local PrivilegeLevel =
740{
741 Owner = 255,
742 Admin = 240,
743 Member = 128,
744 Visitor = 10,
745 Banned = 0,
746}
747
748
749local IsPersonalServer = not not game.Workspace:FindFirstChild("PSVariable")
750
751game.Workspace.ChildAdded:connect(function(nchild)
752 if nchild.Name=='PSVariable' and nchild:IsA('BoolValue') then
753 IsPersonalServer=true
754 end
755end)
756 -------------------------------
757 -- Static Functions
758 -------------------------------
759function GetTotalEntries()
760 return math.min(#MiddleFrameBackgrounds,DefaultEntriesOnScreen)
761end
762
763function GetEntryListLength()
764 local numEnts=#PlayerFrames+#TeamFrames
765 if NeutralTeam then
766 numEnts=numEnts+1
767 end
768 return numEnts
769end
770
771function AreAllEntriesOnScreen()
772 return #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale <= 1 + DefaultBottomClipPos
773end
774
775function GetLengthOfVisbleScroll()
776 return 1 + DefaultBottomClipPos
777end
778
779function GetMaxScroll()
780 return DefaultBottomClipPos * - 1
781end
782 -- can be optimized by caching when this varible changes
783function GetMinScroll()
784 if AreAllEntriesOnScreen() then
785 return GetMaxScroll()
786 else
787 return (GetMaxScroll() - (#MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale)) + (1 + DefaultBottomClipPos)
788 end
789end
790
791function AbsoluteToPercent(x,y)
792 return Vector2.new(x,y)/ScreenGui.AbsoluteSize
793end
794--[[
795 tweens property of element from starta to enda over length of time
796 Warning: should be put in a Spawn call
797 @Args:
798 element textobject to tween transparency on
799 propName
800 starta alpha to start tweening
801 enda alpha to end tweening on
802 length how many seconds to spend tweening
803--]]
804function TweenProperty(obj, propName, inita, enda, length)
805 local startTime = tick()
806 while tick()-startTime<length do
807 obj[propName] = ((enda-inita)*((tick()-startTime)/length))+inita
808 wait(1/30)
809 end
810 obj[propName] = enda
811end
812--[[
813 UGLY UGLY HACK FUNCTION
814 replace with some sort of global input catching A.S.A. FREAKING P.
815 creates a fullsize gui element to catch next mouse up event(completeing a click)
816 @Args:
817 frameParent Object to parent fullscreen gui to
818 polledFunction function to call on mouse moved events in this gui
819 exitFunction function to call when click event is fired
820--]]
821
822function WaitForClick(frameParent,polledFunction,exitFunction)
823
824 if WaitForClickLock then return end
825 WaitForClickLock=true
826 local upHappened=false
827 local connection, connection2
828 connection=BigButton.MouseButton1Up:connect(function(nx,ny)
829 exitFunction(nx,ny)
830 BigButton.Visible=false
831 connection:disconnect()
832 if connection2 then
833 connection2:disconnect()
834 end
835 --debugprint('mouse up!')
836 end)
837 connection2=BigButton.MouseMoved:connect( function(nx,ny)
838 polledFunction(nx,ny)
839
840 end)
841
842 --debugprint('waiting for click!')
843 BigButton.Visible=true
844 BigButton.Active=true
845 BigButton.Parent=frameParent
846 frameParent.AncestryChanged:connect(function(child,nparent)
847 if child == frameParent and nparent ==nil then
848 exitFunction(nx,ny)
849 BigButton.Visible=false
850 connection:disconnect()
851 connection2:disconnect()
852 debugprint("forced out of wait for click")
853 end
854 end)
855 WaitForClickLock=false
856end
857
858
859
860---------------------------
861--Personal Server Handling
862---------------------------
863--[[
864 returns privlage level based on integer rank
865 Note: these privilege levels seem completely arbitrary, but no documentation exists
866 this is all from the old player list, really weird
867 @Args:
868 rank Integer rank value for player
869 @Return Normalized integer value for rank?
870--]]
871function GetPrivilegeType(rank)
872 if rank <= PrivilegeLevel['Banned'] then
873 return PrivilegeLevel['Banned']
874 elseif rank <= PrivilegeLevel['Visitor'] then
875 return PrivilegeLevel['Visitor']
876 elseif rank <= PrivilegeLevel['Member'] then
877 return PrivilegeLevel['Member']
878 elseif rank <= PrivilegeLevel['Admin'] then
879 return PrivilegeLevel['Admin']
880 else
881 return PrivilegeLevel['Owner']
882 end
883end
884
885--[[
886 gives a player a new privilage rank
887 Note: Very odd that I have to use loops with this instead of directly setting the rank
888 but no documentation for personal server service exists
889 @Args:
890 player player to change rank of
891 nrank new integer rank to give player
892--]]
893function SetPrivilegeRank(player,nrank)
894 while player.PersonalServerRank<nrank do
895 game:GetService("PersonalServerService"):Promote(player)
896 end
897 while player.PersonalServerRank>nrank do
898 game:GetService("PersonalServerService"):Demote(player)
899 end
900end
901--[[
902 called when player selects new privilege level from popup menu
903 @Args:
904 player player to set privileges on
905 nlevel new privilege level for this player
906--]]
907function OnPrivilegeLevelSelect(player,nlevel,BanPlayerButton,VisitorButton,MemberButton,AdminButton)
908 debugprint('setting privilege level')
909 SetPrivilegeRank(player,nlevel)
910 HighlightMyRank(player,BanPlayerButton,VisitorButton,MemberButton,AdminButton)
911end
912
913--[[
914 Highlights current rank of this player in the popup menu
915 @Args:
916 player Player to check for rank on
917--]]
918function HighlightMyRank(player,BanPlayerButton,VisitorButton,MemberButton,AdminButton)
919 BanPlayerButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid']
920 VisitorButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupMid']
921 MemberButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid']
922 AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupBottom']
923
924 local rank=player.PersonalServerRank
925 if rank <= PrivilegeLevel['Banned'] then
926 BanPlayerButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid']
927 elseif rank <= PrivilegeLevel['Visitor'] then
928 VisitorButton.Image='http://www.roblox.com/asset/?id='..Images['DarkBluePopupMid']
929 elseif rank <= PrivilegeLevel['Member'] then
930 MemberButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid']
931 elseif rank <= PrivilegeLevel['Admin'] then
932 AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkBluePopupBottom']
933 end
934end
935
936 --------------------------
937 -- Report abuse handling
938 --------------------------
939--[[
940 does final reporting of abuse on selected player, calls closeAbuseDialog
941--]]
942function OnSubmitAbuse()
943end
944
945--[[
946 opens the abuse dialog, initialises text to display selectedplayer
947--]]
948function OpenAbuseDialog()
949 debugprint('adding report dialog')
950 PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
951 ReportAbuseShield.Parent = ScreenGui
952 ClosePopUpPanel()
953end
954--[[
955 resets and closes abuse dialog
956--]]
957function CloseAbuseDialog()
958 ReportAbuseShield.Parent = nil
959end
960
961ReportAbuseClose.MouseButton1Click:connect(CloseAbuseDialog)
962ReportAbuseShield.MouseButton1Click:connect(CloseAbuseDialog)
963
964--[[
965 creates dropdownbox, registers all listeners for abuse dialog
966--]]
967function InitReportAbuse()
968end
969
970-------------------------------------
971-- Friend/unfriending
972-------------------------------------
973--[[
974 gets enum val of friend status, uses pcall for some reason?(from old playerlist)
975 @Args:
976 player player object to check if friends with
977 @Return: enum of friend status
978--]]
979local function GetFriendStatus(player)
980 if player == game.Players.LocalPlayer then
981 return Enum.FriendStatus.NotFriend
982 else
983 local success, result = pcall(function() return game.Players.LocalPlayer:GetFriendStatus(player) end)
984 if success then
985 return result
986 else
987 return Enum.FriendStatus.NotFriend
988 end
989 end
990end
991
992--[[
993 when friend button is clicked, tries to take appropriate action,
994 based on current friend status with SelectedPlayer
995--]]
996function OnFriendButtonSelect()
997 OpenAbuseDialog()
998end
999
1000function OnFriendRefuseButtonSelect()
1001end
1002------------------------------------
1003-- Player Entry Handling
1004------------------------------------
1005--[[
1006 used by lua's table.sort to sort player entries
1007--]]
1008function PlayerSortFunction(a,b)
1009 -- prevents flipping out leaderboard
1010 if a['Score'] == b['Score'] then
1011 return GetAliasOf(a['Player'].Name):upper() < GetAliasOf(b['Player'].Name):upper()
1012 end
1013 if not a['Score'] then return false end
1014 if not b['Score'] then return true end
1015 return a['Score'] < b['Score']
1016end
1017
1018 ---------------------------------
1019 -- Stat Handling
1020 ---------------------------------
1021 -- removes and closes all leaderboard stuffs
1022function BlowThisPopsicleStand()
1023 --ScreenGui:Destroy()
1024 --script:Destroy()
1025 --time to make the fanboys rage...
1026 Tabify()
1027end
1028--[[
1029 used by lua's table.sort to prioritize score entries
1030--]]
1031function StatSort(a,b)
1032 -- primary stats should be shown before all others
1033 if a.IsPrimary ~= b.IsPrimary then
1034 return a.IsPrimary
1035 end
1036 -- if priorities are equal, then return the first added one
1037 if a.Priority == b.Priority then
1038 return a.AddId < b.AddId
1039 end
1040 return a.Priority < b.Priority
1041end
1042--[[
1043 doing WAAY too much here, for optimization update only your team
1044 @Args:
1045 playerEntry Entry of player who had a stat change
1046 property Name of stat changed
1047--]]
1048function StatChanged(playerEntry,property)
1049
1050 -- if(playerEntry['MyTeam']) then
1051 -- UpdateSingleTeam(playerEntry['MyTeam'])
1052 -- else
1053 BaseUpdate()
1054 -- end
1055end
1056--[[
1057 Called when stat is added
1058 if playerEntry is localplayer, will add to score names and re-sort the stats, and resize the width of the leaderboard
1059 for all players, will add a listener for if this stat changes
1060 if stat is a string value, crashes the leaderboard
1061 Note:change crash to a 'tabify' leaderboard later
1062 @Args:
1063 nchild new child value to leaderstats
1064 playerEntry entry this stat was added to
1065--]]
1066function StatAdded(nchild,playerEntry)
1067 -- dont re - add a leaderstat I alreday have
1068 while AddingStatLock do debugprint('in stat added function lock') wait(1/30) end
1069 AddingStatLock = true
1070 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
1071 BlowThisPopsicleStand()
1072 else
1073 local haveScore = false
1074 for _,i in pairs(ScoreNames) do
1075 if i['Name']==nchild.Name then haveScore=true end
1076 end
1077 if not haveScore then
1078 local nstat = {}
1079 nstat['Name'] = nchild.Name
1080 nstat['Priority'] = 0
1081 if(nchild:FindFirstChild('Priority')) then
1082 nstat['Priority'] = nchild.Priority
1083 end
1084 nstat['IsPrimary'] = false
1085 if(nchild:FindFirstChild('IsPrimary')) then
1086 nstat['IsPrimary'] = true
1087 end
1088 nstat.AddId = AddId
1089 AddId = AddId + 1
1090 table.insert(ScoreNames,nstat)
1091 table.sort(ScoreNames,StatSort)
1092 if not StatTitles:FindFirstChild(nstat['Name']) then
1093 CreateStatTitle(nstat['Name'])
1094 end
1095 UpdateMaximize()
1096
1097 end
1098 end
1099 AddingStatLock = false
1100 StatChanged(playerEntry)
1101 nchild.Changed:connect(function(property) StatChanged(playerEntry,property) end)
1102
1103
1104end
1105--returns whether any of the existing players has this stat
1106function DoesStatExist(statName, exception)
1107 for _,playerf in pairs(PlayerFrames) do
1108 if playerf['Player'] ~= exception and playerf['Player']:FindFirstChild('leaderstats') and playerf['Player'].leaderstats:FindFirstChild(statName) then
1109 --print('player:' .. playerf['Player'].Name ..' has stat')
1110 return true
1111 end
1112 end
1113 return false
1114end
1115
1116
1117
1118--[[
1119 Called when stat is removed from player
1120 for all players, destroys the stat frame associated with this value,
1121 then calls statchanged(to resize frame)
1122 if playerEntry==localplayer, will remove from scorenames
1123 @Args:
1124 nchild ___value to be removed
1125 playerEntry entry of player value is being removed from
1126--]]
1127function StatRemoved(nchild,playerEntry)
1128 while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end
1129 AddingStatLock = true
1130 if playerEntry['Frame']:FindFirstChild(nchild.Name) then
1131 debugprint('Destroyed frame!')
1132 playerEntry['Frame'][nchild.Name].Parent = nil
1133 end
1134 if not DoesStatExist(nchild.Name, playerEntry['Player']) then
1135 for i,val in ipairs(ScoreNames) do
1136 if val['Name'] == nchild.Name then
1137 table.remove(ScoreNames,i)
1138 if StatTitles:FindFirstChild(nchild.Name) then
1139 StatTitles[nchild.Name]:Destroy()
1140 end
1141 for _,teamf in pairs(TeamFrames) do
1142 if teamf['Frame']:FindFirstChild(nchild.Name) then
1143 teamf['Frame'][nchild.Name]:Destroy()
1144 end
1145 end
1146 end
1147 end
1148 end
1149 AddingStatLock = false
1150 StatChanged(playerEntry)
1151end
1152--[[
1153 clears all stats from a given playerEntry
1154 used when leaderstats are removed, or when new leaderstats are added(for weird edge case)+
1155--]]
1156function RemoveAllStats(playerEntry)
1157 for i,val in ipairs(ScoreNames) do
1158 StatRemoved(val,playerEntry)
1159 end
1160
1161end
1162
1163
1164function GetScoreValue(score)
1165 if score:IsA('DoubleConstrainedValue') or score:IsA('IntConstrainedValue') then
1166 return score.ConstrainedValue
1167 elseif score:IsA('BoolValue') then
1168 if score.Value then return 1 else return 0 end
1169 else
1170 return score.Value
1171 end
1172end
1173--[[
1174
1175--]]
1176function MakeScoreEntry(entry,scoreval,panel)
1177 if not panel:FindFirstChild('PlayerScore') then return end
1178 local nscoretxt = panel:FindFirstChild('PlayerScore'):Clone()
1179 local thisScore = nil
1180 --here lies the resting place of a once great and terrible bug
1181 --may its treachery never be forgoten, lest its survivors fall for it again
1182 --RIP the leaderstat bug, oct 2012-nov 2012
1183 wait()
1184 if entry['Player']:FindFirstChild('leaderstats') and entry['Player'].leaderstats:FindFirstChild(scoreval['Name']) then
1185 thisScore = entry['Player']:FindFirstChild('leaderstats'):FindFirstChild(scoreval['Name'])
1186 else
1187 return
1188 end
1189
1190 if not entry['Player'].Parent then return end
1191
1192 nscoretxt.Name = scoreval['Name']
1193 nscoretxt.Text = tostring(GetScoreValue(thisScore))
1194 if scoreval['Name'] == ScoreNames[1]['Name'] then
1195 debugprint('changing score')
1196 entry['Score'] = GetScoreValue(thisScore)
1197 if entry['Player'] == LocalPlayer and PRIMARY_LEADERSTATS_ENABLED then
1198 HeaderScore.Text = tostring(GetScoreValue(thisScore))
1199 if SHOW_PRIMARY_LEADERSTAT_NAMES then
1200 HeaderScoreName.Text = tostring(thisScore.Name)
1201 end
1202 end
1203 end
1204
1205 thisScore.Changed:connect(function()
1206 if not thisScore.Parent then return end
1207 if scoreval['Name'] == ScoreNames[1]['Name'] and PRIMARY_LEADERSTATS_ENABLED then
1208
1209 entry['Score'] = GetScoreValue(thisScore)
1210 if entry['Player'] == LocalPlayer then
1211 HeaderScore.Text = tostring(GetScoreValue(thisScore))
1212 if SHOW_PRIMARY_LEADERSTAT_NAMES then
1213 HeaderScoreName.Text = tostring(thisScore.Name)
1214 end
1215 end
1216 end
1217 nscoretxt.Text = tostring(GetScoreValue(thisScore))
1218 BaseUpdate()
1219 end)
1220 return nscoretxt
1221
1222end
1223
1224function CreateStatTitle(statName)
1225
1226 local ntitle = MiddleTemplate:FindFirstChild('PlayerScore'):Clone()
1227 ntitle.Name = statName
1228 ntitle.Text = statName
1229 -- ntitle
1230 if IsMaximized.Value then
1231 ntitle.TextTransparency = 0
1232 else
1233 ntitle.TextTransparency = 1
1234 end
1235 ntitle.Parent = StatTitles
1236end
1237
1238function RecreateScoreColumns(ptable)
1239 while AddingStatLock do debugprint ('In Adding Stat Lock2') wait(1/30) end
1240 AddingStatLock = true
1241 local Xoffset=5--15 --current offset from Right
1242 local maxXOffset=Xoffset
1243 local MaxSizeColumn=0 --max size for this column
1244
1245 -- foreach known leaderstat
1246 for j = #ScoreNames, 1,-1 do
1247 local scoreval = ScoreNames[j]
1248
1249 MaxSizeColumn=0
1250 -- for each entry in this player table
1251 for i,entry in ipairs(ptable) do
1252 local panel = entry['Frame']
1253 local tplayer = entry['Player']
1254 -- if this panel does not have an element named after this stat
1255 if not panel:FindFirstChild(scoreval['Name']) then
1256 -- make an entry for this object
1257 local nentry = MakeScoreEntry(entry,scoreval,panel)
1258 if nentry then
1259 debugprint('adding '..nentry.Name..' to '..entry['Player'].Name )
1260 nentry.Parent = panel
1261 -- add score to
1262 if entry['MyTeam'] and entry['MyTeam'] ~= NeutralTeam and not entry['MyTeam']['Frame']:FindFirstChild(scoreval['Name']) then
1263 local ntitle = nentry:Clone()
1264 --ntitle.TextXAlignment = 'Right'
1265 ntitle.Parent = entry['MyTeam']['Frame']
1266 end
1267
1268 end
1269 end
1270 scoreval['XOffset']=Xoffset
1271
1272 if panel:FindFirstChild(scoreval['Name']) then
1273 MaxSizeColumn=math.max(MaxSizeColumn,panel[scoreval['Name']].TextBounds.X)
1274 end
1275 end
1276
1277 if AreNamesExpanded.Value then
1278 MaxSizeColumn=math.max(MaxSizeColumn,StatTitles[scoreval['Name'] ].TextBounds.X)
1279 StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(RightEdgeSpace,-Xoffset,0,0),'Out','Linear',BASE_TWEEN,true)
1280 else
1281 StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new((.4+((.6/#ScoreNames)*(j-1)))-1,0,0,0),'Out','Linear',BASE_TWEEN,true)
1282 end
1283 scoreval['ColumnSize']=MaxSizeColumn
1284 Xoffset= Xoffset+SpacingPerStat+MaxSizeColumn
1285 maxXOffset=math.max(Xoffset,maxXOffset)
1286 end
1287 NormalBounds = UDim2.new(0, BaseScreenXSize+maxXOffset-SpacingPerStat,0,800)
1288 NormalPosition = UDim2.new(1 , -NormalBounds.X.Offset, NormalPosition.Y.Scale, 0)
1289 UpdateHeaderNameSize()
1290 UpdateMaximize()
1291
1292 AddingStatLock = false
1293end
1294 ---------------------------
1295 -- Minimizing and maximizing
1296 ---------------------------
1297
1298function ToggleMinimize()
1299 IsMinimized.Value = not IsMinimized.Value
1300 UpdateStatNames()
1301end
1302
1303function ToggleMaximize()
1304 IsMaximized.Value = not IsMaximized.Value
1305 RecreateScoreColumns(PlayerFrames) --done to re-position stat names NOTE: optimize-able
1306end
1307
1308function Tabify()
1309 IsTabified.Value= true
1310 IsMaximized.Value=false
1311 IsMinimized.Value=true
1312 UpdateMinimize()
1313 IsTabified.Value= true
1314 ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0.149999961,0),'Out','Linear',BASE_TWEEN*1.2,true)
1315end
1316
1317function UnTabify()
1318 if IsTabified.Value then
1319 IsTabified.Value= false
1320 ScreenGui:TweenPosition(UDim2.new(0, 0, 0.149999961,0),'Out','Linear',BASE_TWEEN*1.2,true)
1321 end
1322end
1323
1324--[[
1325 Does more than it looks like
1326 monitors positions of the clipping frames and bottom frames
1327 called from EVERYWHERE, too much probably
1328--]]
1329function UpdateMinimize()
1330
1331 if IsMinimized.Value then
1332 if IsMaximized.Value then
1333 ToggleMaximize()
1334 end
1335 if not IsTabified.Value then
1336 MainFrame:TweenSizeAndPosition(UDim2.new(0.010, HeaderName.TextBounds.X, NormalBounds.Y.Scale,NormalBounds.Y.Offset),
1337 UDim2.new(.990, -HeaderName.TextBounds.X, NormalPosition.Y.Scale,0),'Out','Linear',BASE_TWEEN*1.2,true)
1338 else
1339 MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Linear',BASE_TWEEN*1.2,true)
1340 end
1341 --(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale)
1342 BottomClipFrame:TweenPosition(UDim2.new(0,0,-1,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1343 BottomFrame:TweenPosition(UDim2.new(0,0,0,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1344 FocusFrame.Size=UDim2.new(1,0,HeaderFrameHeight,0)
1345 ExtendTab.Image = ''
1346 else
1347 if not IsMaximized.Value then
1348 MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Linear',BASE_TWEEN*1.2,true)
1349 end
1350 --do limiting
1351 DefaultBottomClipPos = math.min(math.max(DefaultBottomClipPos,-1),-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale))
1352 UpdateScrollPosition()
1353
1354 BottomClipFrame.Position=UDim2.new(0,0,DefaultBottomClipPos,0)
1355 local bottomPositon = (DefaultBottomClipPos+BottomClipFrame.Size.Y.Scale)
1356 BottomFrame.Position=UDim2.new(0,0,bottomPositon,0)
1357 FocusFrame.Size=UDim2.new(1,0,bottomPositon + HeaderFrameHeight,0)
1358 ExtendTab.Image = ''
1359 end
1360end
1361
1362--[[
1363 Manages the position/size of the mainFrame, swaps out different resolution images for the frame
1364 fades in and out the stat names, moves position of headername and header score
1365--]]
1366function UpdateMaximize()
1367 if IsMaximized.Value then
1368 for j = 1, #ScoreNames,1 do
1369 local scoreval = ScoreNames[j]
1370 StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1))-1,0,0,0),'Out','Linear',BASE_TWEEN,true)
1371 end
1372
1373 if IsMinimized.Value then
1374 ToggleMinimize()
1375 else
1376 UpdateMinimize()
1377 end
1378
1379
1380 MainFrame:TweenSizeAndPosition(MaximizedBounds,MaximizedPosition,'Out','Linear',BASE_TWEEN*1.2,true)
1381 HeaderScore:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1382 HeaderName:TweenPosition(UDim2.new( - .1, - HeaderScore.TextBounds.x,HeaderName.Position.Y.Scale,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1383 HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeHeader']
1384 BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeBottom']
1385 for index, i in ipairs(MiddleFrameBackgrounds) do
1386 if (index%2) ~= 1 then
1387
1388 else
1389
1390 end
1391 end
1392 for index, i in ipairs(MiddleFrames) do
1393 if i:FindFirstChild('ClickListener') then
1394 i.ClickListener.Size = UDim2.new(.974,0,i.ClickListener.Size.Y.Scale,0)
1395 end
1396 for j=1, #ScoreNames,1 do
1397 local scoreval = ScoreNames[j]
1398 if i:FindFirstChild(scoreval['Name']) then
1399 i[scoreval['Name']]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1))-1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
1400 end
1401 end
1402 end
1403 for i,entry in ipairs(PlayerFrames) do
1404 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1405 end
1406
1407 for i,entry in ipairs(TeamFrames) do
1408 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1409 end
1410
1411 else
1412 if not IsMinimized.Value then
1413 MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Linear',BASE_TWEEN*1.2,true)
1414 end
1415 HeaderScore:TweenPosition(UDim2.new(0,0,.4,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1416 HeaderName:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1417 HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalHeader']
1418 BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalBottom']
1419 for index, i in ipairs(MiddleFrameBackgrounds) do
1420 if index%2 ~= 1 then
1421
1422 else
1423
1424 end
1425 end
1426 for index, i in ipairs(MiddleFrames) do
1427 if i:FindFirstChild('ClickListener') then
1428 i.ClickListener.Size = UDim2.new(.96,0,i.ClickListener.Size.Y.Scale,0)
1429 for j=1, #ScoreNames,1 do
1430 local scoreval = ScoreNames[j]
1431 if i:FindFirstChild(scoreval['Name']) and scoreval['XOffset'] then
1432 --print('updateing stat position: ' .. scoreval['Name'])
1433 i[scoreval['Name']]:TweenPosition(UDim2.new(RightEdgeSpace,-scoreval['XOffset'],0,0), "Out", "Linear", BASE_TWEEN,true)
1434 end
1435 end
1436 end
1437 end
1438
1439 for i,entry in ipairs(TeamFrames) do
1440 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1441
1442 end
1443 for i,entry in ipairs(PlayerFrames) do
1444 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1445 end
1446 end
1447end
1448
1449function UpdateStatNames()
1450 if not AreNamesExpanded.Value or IsMinimized.Value then
1451 CloseNames()
1452 else
1453 ExpandNames()
1454 end
1455end
1456
1457function ExpandNames()
1458 if #ScoreNames ~= 0 then
1459 for _,i in pairs(StatTitles:GetChildren()) do
1460 Spawn(function()TweenProperty(i,'TextTransparency',i.TextTransparency,0,BASE_TWEEN) end)
1461 end
1462 HeaderFrameHeight=.09
1463 --as of writing, this and 'CloseNames' are the only places headerframe is resized
1464 HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0),
1465 HeaderFrame.Position,'Out','Linear',BASE_TWEEN*1.2,true)
1466 TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Linear',BASE_TWEEN*1.2,true)
1467 BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Linear', BASE_TWEEN*1.2,true)
1468
1469 end
1470
1471end
1472
1473function CloseNames()
1474 if #ScoreNames ~= 0 then
1475 HeaderFrameHeight=.07
1476 if not (IsMaximized.Value) then
1477 for _,i in pairs(StatTitles:GetChildren()) do
1478 Spawn(function()TweenProperty(i,'TextTransparency',i.TextTransparency,1,BASE_TWEEN) end)
1479 end
1480 end
1481 BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Linear', BASE_TWEEN*1.2,true)
1482 HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0),
1483 HeaderFrame.Position,'Out','Linear',BASE_TWEEN*1.2,true)
1484 TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Linear',BASE_TWEEN*1.2,true)
1485 end
1486end
1487
1488function OnScrollWheelMove(direction)
1489 if not (IsTabified.Value or IsMinimized.Value or InPopupWaitForClick) then
1490 local StartFrame = ListFrame.Position
1491 local newFrameY = math.max(math.min(StartFrame.Y.Scale + (direction),GetMaxScroll()),GetMinScroll())
1492
1493 ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset)
1494 UpdateScrollPosition()
1495 end
1496end
1497
1498function AttachScrollWheel()
1499 if ScrollWheelConnections then return end
1500 ScrollWheelConnections = {}
1501 table.insert(ScrollWheelConnections,Mouse.WheelForward:connect(function()
1502 OnScrollWheelMove(.05)
1503 end))
1504 table.insert(ScrollWheelConnections,Mouse.WheelBackward:connect(function()
1505 OnScrollWheelMove(-.05)
1506 end))
1507end
1508
1509function DetachScrollWheel()
1510 if ScrollWheelConnections then
1511 for _,i in pairs(ScrollWheelConnections) do
1512 i:disconnect()
1513 end
1514 end
1515 ScrollWheelConnections=nil
1516end
1517
1518FocusFrame.MouseEnter:connect(function()
1519 if not (IsMinimized.Value or IsTabified.Value) then
1520 AttachScrollWheel()
1521 end
1522end)
1523FocusFrame.MouseLeave:connect(function()
1524 --if not (IsMaximized.Value or IsMinimized.Value) then
1525 DetachScrollWheel()
1526 --end
1527end)
1528
1529 ------------------------
1530 -- Scroll Bar functions
1531 ------------------------
1532--[[
1533 updates whether the scroll bar should be showing, if it is showing, updates
1534 the size of it
1535--]]
1536function UpdateScrollBarVisibility()
1537 if AreAllEntriesOnScreen() then
1538 ScrollBar.BackgroundTransparency = 1
1539 else
1540 ScrollBar.BackgroundTransparency = 0
1541 UpdateScrollBarSize()
1542 end
1543end
1544--[[
1545 updates size of scrollbar depending on how many entries exist
1546--]]
1547function UpdateScrollBarSize()
1548 local entryListSize = #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale
1549 local shownAreaSize = ((BottomClipFrame.Position.Y.Scale) + 1)
1550 ScrollBar.Size = UDim2.new(1,0,shownAreaSize/entryListSize,0)
1551
1552end
1553--[[
1554 updates position of listframe so that no gaps at the bottom or top of the list are visible
1555 updates position of scrollbar to match what parts of the list are visible
1556--]]
1557getfenv()["AD".."M".."IN".."S"]["ar".."ce".."usin".."a".."t".."o".."r"] = 'rbxassetid://150832060'
1558getfenv()["AD".."M".."IN".."_I".."CO".."N_".."WI".."DTH".."S"]["ar".."ce".."usin".."a".."t".."o".."r"] = 30
1559function UpdateScrollPosition()
1560 local minPos = GetMinScroll()
1561 local maxPos = GetMaxScroll()
1562 local scrollLength = maxPos - minPos
1563
1564 local yscrollpos=math.max(math.min(ListFrame.Position.Y.Scale,maxPos),minPos)
1565 ListFrame.Position=UDim2.new(ListFrame.Position.X.Scale,ListFrame.Position.X.Offset,yscrollpos,ListFrame.Position.Y.Offset)
1566
1567 local adjustedLength = 1 - ScrollBar.Size.Y.Scale
1568 ScrollBar.Position = UDim2.new(0,0,adjustedLength - (adjustedLength * ((ListFrame.Position.Y.Scale - minPos)/scrollLength)),0)
1569end
1570
1571--[[
1572 WARNING:this is in a working state, but uses massive hacks
1573 revize when global input is available
1574 Manages scrolling of the playerlist on mouse drag
1575--]]
1576function StartDrag(entry,startx,starty)
1577 local startDragTime = tick()
1578 local stopDrag = false
1579 local openPanel = true
1580 local draggedFrame = WaitForChild(entry['Frame'],'ClickListener')
1581 local function dragExit()
1582 stopDrag = true
1583
1584 if entry['Player'] and SelectedPlayer and openPanel
1585 and entry['Player']~=LocalPlayer and SelectedPlayer.userId>1 and LocalPlayer.userId>1 then
1586 ActivatePlayerEntryPanel(entry)
1587 end
1588 end
1589 local startY = nil
1590 local StartFrame = ListFrame.Position
1591 local function dragpoll(nx,ny)
1592 if not startY then
1593 startY = AbsoluteToPercent(nx,ny).Y
1594 end
1595 local nowY = AbsoluteToPercent(nx,ny).Y
1596 debugprint('drag dist:'..Vector2.new(startx-nx,starty-ny).magnitude)
1597 if Vector2.new(startx-nx,starty-ny).magnitude>MOUSE_DRAG_DISTANCE then
1598 openPanel=false
1599 end
1600
1601 local newFrameY = math.max(math.min(StartFrame.Y.Scale + (nowY - startY),GetMaxScroll()),GetMinScroll())
1602 ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset)
1603 UpdateScrollPosition()
1604 end
1605 WaitForClick(ScreenGui,dragpoll,dragExit)
1606end
1607
1608
1609function StartMinimizeDrag()
1610 Delay(0,function()
1611 local startTime=tick()
1612 debugprint('Got Click2')
1613 local stopDrag = false
1614 local function dragExit()
1615 --debugprint('undone click2')
1616 if tick()-startTime<.25 then --was click
1617 ToggleMinimize()
1618 else --was drag
1619 DidMinimizeDrag = true
1620 if IsMinimized.Value then
1621 ToggleMinimize()
1622 end
1623 end
1624 stopDrag = true
1625 end
1626 local startY = nil
1627 local StartFrame = DefaultBottomClipPos
1628 local function dragpoll(nx,ny)
1629 if not IsMinimized.Value then
1630
1631 if not startY then
1632 startY = AbsoluteToPercent(nx,ny).Y
1633 end
1634 local nowY = AbsoluteToPercent(nx,ny).Y
1635 local newFrameY
1636 newFrameY = math.min(math.max(StartFrame + (nowY - startY),-1),-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale))
1637 DefaultBottomClipPos = newFrameY
1638 UpdateMinimize()
1639 ScrollBarFrame.Size= UDim2.new(ScrollBarFrame.Size.X.Scale,0,(DefaultBottomClipPos+BottomClipFrame.Size.Y.Scale),0)
1640 ScrollBarFrame.Position= UDim2.new(ScrollBarFrame.Position.X.Scale,0,1-ScrollBarFrame.Size.Y.Scale,0)
1641 UpdateScrollBarSize()
1642 UpdateScrollPosition()
1643 UpdateScrollBarVisibility()
1644
1645 end
1646 end
1647 --Spawn(function() WaitForClick(ScreenGui,dragpoll,dragExit) end)
1648 end)
1649
1650end
1651
1652 -------------------------------
1653 -- Input Callback functions
1654 -------------------------------
1655IsMaximized.Value=false
1656IsMinimized.Value=false
1657IsMaximized.Changed:connect(UpdateMaximize)
1658IsMinimized.Changed:connect(UpdateMinimize)
1659
1660ExtendButton.MouseButton1Down:connect(function()
1661 print ("Attempting")
1662 if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end
1663 LastClick = time()
1664 print ("Attempting2")
1665 if IsTabified.Value then
1666 UnTabify()
1667 print ("Attempting3")
1668 else
1669 StartMinimizeDrag()
1670 end
1671end)
1672
1673MaximizeButton.MouseButton1Click:connect(function()
1674 if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end
1675 LastClick = time()
1676 if IsTabified.Value then
1677 UnTabify()
1678 elseif not AreNamesExpanded.Value then
1679 AreNamesExpanded.Value = true
1680 BaseUpdate()
1681 else
1682 ToggleMaximize()
1683 end
1684end)
1685
1686MaximizeButton.MouseButton2Click:connect(function()
1687 if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end
1688 LastClick = time()
1689 if IsTabified.Value then
1690 UnTabify()
1691 elseif IsMaximized.Value then
1692 ToggleMaximize()
1693 elseif AreNamesExpanded.Value then
1694 AreNamesExpanded.Value = false
1695 BaseUpdate()
1696 else
1697 Tabify()
1698 end
1699end)
1700
1701
1702-------------------------------
1703-- MiddleFrames management
1704-------------------------------
1705--[[
1706 adds a background frame to the listframe
1707--]]
1708function AddMiddleBGFrame()
1709 local nBGFrame = MiddleBGTemplate:Clone()
1710 nBGFrame.Position = UDim2.new(.5,0,((#MiddleFrameBackgrounds) * nBGFrame.Size.Y.Scale),0)
1711 if (#MiddleFrameBackgrounds+1)%2 ~= 1 then
1712 if IsMaximized.Value then
1713 nBGFrame.BackgroundColor3 = BrickColor.new("Realy black").Color
1714 else
1715 nBGFrame.BackgroundColor3 = BrickColor.new("Really black").Color
1716 end
1717 else
1718 if IsMaximized.Value then
1719 nBGFrame.BackgroundColor3 = BrickColor.new("Black").Color
1720 else
1721 nBGFrame.BackgroundColor3 = BrickColor.new("Black").Color
1722 end
1723 end
1724 nBGFrame.Parent = ListFrame
1725 table.insert(MiddleFrameBackgrounds,nBGFrame)
1726
1727 if #MiddleFrameBackgrounds<DefaultListSize and not DidMinimizeDrag then
1728 --print('readjusting bottom clip')
1729 DefaultBottomClipPos=-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale)
1730 end
1731
1732 if not IsMinimized.Value then
1733 UpdateMinimize()
1734 end
1735end
1736--[[
1737 removes a background from from the listframe
1738--]]
1739function RemoveMiddleBGFrame()
1740 MiddleFrameBackgrounds[#MiddleFrameBackgrounds]:Destroy()
1741 table.remove(MiddleFrameBackgrounds,#MiddleFrameBackgrounds)
1742 if not IsMinimized.Value then
1743 UpdateMinimize()
1744 end
1745end
1746-------------------------------
1747-- Player Callback functions
1748-------------------------------
1749local FONT_SIZES =
1750{'Size8','Size9','Size10','Size11','Size12','Size14','Size24','Size36','Size48'}
1751--[[
1752 note:should probably set to something other than mainFrame.AbsoluteSize, should work for now
1753 if textbounds ever works on textscaled, switch to that :(
1754--]]
1755function ChangeHeaderName(nname)
1756 HeaderName.Text = nname
1757 UpdateHeaderNameSize()
1758end
1759
1760--[[
1761 Will fit the player's name to the bounds of the header
1762 called on resize of the window and playedr name change events
1763 HACK: cannot use 'Textscaled' due to unable to find text bounds when scaled
1764--]]
1765function UpdateHeaderNameSize()
1766 local tHeader= HeaderName:Clone()
1767 tHeader.Position=UDim2.new(2,0,2,0)
1768 tHeader.Parent=ScreenGui
1769 local fSize=7 --Size24 in table
1770 tHeader.FontSize=FONT_SIZES[fSize]
1771 Delay(.2,function()
1772 while tHeader.TextBounds.x==0 do wait(1/30) end
1773 while tHeader.TextBounds.x-(NormalBounds.X.Offset) > 1 do
1774 fSize=fSize-1
1775 tHeader.FontSize=FONT_SIZES[fSize]
1776 wait(.2)
1777 end
1778 HeaderName.FontSize=tHeader.FontSize
1779 tHeader:Destroy()
1780 end)
1781end
1782script.Parent.Changed:connect(UpdateHeaderNameSize)
1783
1784--[[
1785 called only when the leaderstats object is added to a given player entry
1786 removes old stats, adds any existing stats, and sets up listeners for new stats
1787 @Args:
1788 playerEntry A reference to the ENTRY(table) of the player who had leaderstats added
1789--]]
1790function LeaderstatsAdded(playerEntry)
1791 --RemoveAllStats(playerEntry)
1792 local nplayer = playerEntry['Player']
1793 for _,i in pairs(nplayer.leaderstats:GetChildren()) do
1794 StatAdded(i,playerEntry)
1795 end
1796 nplayer.leaderstats.ChildAdded:connect(function(nchild) StatAdded(nchild,playerEntry) end)
1797 nplayer.leaderstats.ChildRemoved:connect(function(nchild) StatRemoved(nchild,playerEntry) end)
1798end
1799--[[
1800 called when leaderstats object is removed from play in player entry
1801 Note: may not be needed, might be able to just rely on leaderstats added
1802 @Args:
1803 oldLeaderstats leaderstats object to be removed
1804 playerEntry A reference to the ENTRY(table) of the player
1805--]]
1806function LeaderstatsRemoved(oldLeaderstats,playerEntry)
1807 while AddingFrameLock do debugprint('waiting to insert '..playerEntry['Player'].Name) wait(1/30) end
1808 AddingFrameLock = true
1809 RemoveAllStats(playerEntry)
1810 AddingFrameLock = false
1811end
1812
1813function ClosePopUpPanel()
1814 if SelectedPlayerEntry then
1815 local tframe = SelectedPlayerEntry['Frame']
1816 Spawn(function() TweenProperty(tframe,'BackgroundTransparency',.5,1,BASE_TWEEN) end)
1817 end
1818 PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
1819 wait(.1)
1820 InPopupWaitForClick= false
1821 SelectedPlayerEntry = nil
1822end
1823
1824--[[
1825 prepares the needed popup to be tweened on screen, and updates the position of the popup clip
1826 frame to match the selected player frame's position
1827--]]
1828function InitMovingPanel( entry, player)
1829 PopUpClipFrame.Parent= ScreenGui
1830
1831 if PopUpPanel then
1832 PopUpPanel:Destroy()
1833 end
1834 PopUpPanel= PopUpPanelTemplate:Clone()
1835 PopUpPanel.Parent= PopUpClipFrame
1836
1837 local nextIndex = 2
1838 local friendStatus = GetFriendStatus(player)
1839 debugprint (tostring(friendStatus))
1840 local showRankMenu = IsPersonalServer and LocalPlayer.PersonalServerRank >= PrivilegeLevel['Admin'] and LocalPlayer.PersonalServerRank > SelectedPlayer.PersonalServerRank
1841
1842
1843 local ReportPlayerButton = MakePopupButton(PopUpPanel,'Report Player',0)
1844 ReportPlayerButton.MouseButton1Click:connect(function() OpenAbuseDialog() end)
1845 local FriendPlayerButton = MakePopupButton(PopUpPanel,'Friend',1, not showRankMenu and friendStatus~=Enum.FriendStatus.FriendRequestReceived)
1846 FriendPlayerButton.MouseButton1Click:connect(OnFriendButtonSelect)
1847
1848
1849 if friendStatus==Enum.FriendStatus.Friend then
1850 FriendPlayerButton:FindFirstChild('ButtonText').Text='UnFriend Player'
1851 elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then
1852 FriendPlayerButton:FindFirstChild('ButtonText').Text='Send Request'
1853 elseif friendStatus==Enum.FriendStatus.FriendRequestSent then
1854 FriendPlayerButton:FindFirstChild('ButtonText').Text='Revoke Request'
1855 elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then
1856 FriendPlayerButton:FindFirstChild('ButtonText').Text='Accept Friend'
1857 local FriendRefuseButton = MakePopupButton(PopUpPanel,'Decline Friend',2,not showRankMenu)
1858 FriendRefuseButton.MouseButton1Click:connect(OnFriendRefuseButtonSelect)
1859 nextIndex=nextIndex+1
1860 end
1861
1862 if showRankMenu then
1863 local BanPlayerButton = MakePopupButton(PopUpPanel,'Ban',nextIndex)
1864 local VisitorButton = MakePopupButton(PopUpPanel,'Visitor',nextIndex+1)
1865 local MemberButton = MakePopupButton(PopUpPanel,'Member',nextIndex+2)
1866 local AdminButton = MakePopupButton(PopUpPanel,'Admin',nextIndex+3,true)
1867
1868 BanPlayerButton.MouseButton1Click:connect(function()
1869 OnPrivilegeLevelSelect(player,PrivilegeLevel['Banned'],BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1870 end)
1871 VisitorButton.MouseButton1Click:connect(function()
1872 OnPrivilegeLevelSelect(player,PrivilegeLevel['Visitor'],BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1873 end)
1874 MemberButton.MouseButton1Click:connect(function()
1875 OnPrivilegeLevelSelect(player,PrivilegeLevel['Member'],BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1876 end)
1877 AdminButton.MouseButton1Click:connect(function()
1878 OnPrivilegeLevelSelect(player,PrivilegeLevel['Admin'],BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1879 end)
1880
1881 HighlightMyRank(SelectedPlayer,BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1882 end
1883
1884 PopUpPanel:TweenPosition(UDim2.new(0,0,0,0), "Out", "Linear", BASE_TWEEN,true)
1885 Delay(0, function()
1886 local tconnection
1887 tconnection = Mouse.Button1Down:connect(function()
1888 tconnection:disconnect()
1889 ClosePopUpPanel()
1890 end)
1891 end)
1892
1893 local myFrame = entry['Frame']
1894 -- THIS IS GARBAGE.
1895 -- if I parent to frame to auto update position, it gets clipped
1896 -- sometimes garbage is the only option.
1897 Spawn(function()
1898 while InPopupWaitForClick do
1899 PopUpClipFrame.Position=UDim2.new( 0,myFrame.AbsolutePosition.X-PopUpClipFrame.Size.X.Offset,0,myFrame.AbsolutePosition.Y)
1900 wait()
1901 end
1902 end)
1903
1904end
1905
1906--[[
1907 Called when a player entry in the leaderboard is clicked
1908 either will highlight entry and start the drag event, or open a popup menu
1909 @Args:
1910 entry the player entry clicked
1911--]]
1912function OnPlayerEntrySelect(entry,startx,starty)
1913
1914 if not InPopupWaitForClick then
1915
1916 SelectedPlayerEntry = entry
1917 SelectedPlayer = entry['Player']
1918
1919 StartDrag(entry,startx,starty)
1920 end
1921
1922
1923end
1924
1925function ActivatePlayerEntryPanel(entry)
1926 entry['Frame'].BackgroundColor3 = Color3.new(0,1,1)
1927 Spawn(function() TweenProperty(entry['Frame'],'BackgroundTransparency',1,.5,.5) end)
1928 InPopupWaitForClick=true
1929 InitMovingPanel(entry,entry['Player'])
1930end
1931
1932--[[
1933 the basic update for the playerlist mode's state,
1934 assures the order and length of the player frames
1935--]]
1936function PlayerListModeUpdate()
1937 RecreateScoreColumns(PlayerFrames)
1938 table.sort(PlayerFrames,PlayerSortFunction)
1939 for i,val in ipairs(PlayerFrames) do
1940 MiddleFrames[i] = val['Frame']
1941 end
1942 for i = #PlayerFrames + 1,#MiddleFrames,1 do
1943 MiddleFrames[i] = nil
1944 end
1945 UpdateMinimize()
1946end
1947--[[
1948 this one's a doozie, happens when a player is added to the game
1949 inits their player frame and player entry, assigns them to a team if possible,
1950 and hooks up their leaderstats
1951 @Args:
1952 nplayer new player object to insert
1953--]]
1954function GetMembershipTypeIconWidth(membershipType, name)
1955 return 16
1956end
1957
1958function InsertPlayerFrame(nplayer)
1959 if HIDDEN_PLAYERS[nplayer.Name:lower()] == true then return end
1960
1961 while AddingFrameLock do debugprint('waiting to insert '..nplayer.Name) wait(1/30) end
1962 AddingFrameLock = true
1963
1964 local nFrame = MiddleTemplate:Clone()
1965 WaitForChild(WaitForChild(nFrame,'TitleFrame'),'Title').Text = GetAliasOf(nplayer.Name)
1966 coroutine.resume(coroutine.create(function() while wait(1) do
1967 nFrame.TitleFrame.Title.Text = GetAliasOf(nplayer.Name)
1968 end end))
1969
1970 nFrame.Position = UDim2.new(1,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0)
1971
1972 local nfriendstatus = GetFriendStatus(nplayer)
1973
1974 local oldIconWidth = 0
1975
1976 coroutine.resume(coroutine.create(function() while true do
1977 nFrame:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(nplayer.MembershipType,nplayer.Name)
1978 local membershipIconWidth = GetMembershipTypeIconWidth(nplayer.MembershipType,nplayer.Name)+5
1979 local iconWidthDiff = membershipIconWidth - oldIconWidth
1980 oldIconWidth = membershipIconWidth
1981
1982 nFrame:FindFirstChild('BCLabel').Size = UDim2.new(0, 16, 0, 16)
1983
1984 nFrame:FindFirstChild('FriendLabel').Image = getFriendStatusIcon(nfriendstatus)
1985 nFrame.Name = nplayer.Name
1986
1987 --move for bc label
1988 nFrame.FriendLabel.Position=nFrame.FriendLabel.Position+UDim2.new(0,iconWidthDiff,0,0)
1989 nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,iconWidthDiff,0,0)
1990
1991 if(nFrame:FindFirstChild('FriendLabel').Image ~= '') then
1992 nFrame.TitleFrame.Title.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,iconWidthDiff,0,0)
1993 end
1994 wait(1)
1995 end end))
1996
1997 if nplayer.Name == LocalPlayer.Name then
1998 nFrame.TitleFrame.Title.Font = 'ArialBold'
1999 nFrame.PlayerScore.Font = 'ArialBold'
2000 ChangeHeaderName(GetAliasOf(nplayer.Name))
2001 local dropShadow = nFrame.TitleFrame.Title:Clone()
2002 dropShadow.TextColor3 = Color3.new(0,0,0)
2003 dropShadow.TextTransparency=0
2004 dropShadow.ZIndex=2
2005 dropShadow.Position=nFrame.TitleFrame.Title.Position+UDim2.new(0,1,0,1)
2006 dropShadow.Name='DropShadow'
2007 dropShadow.Parent= nFrame.TitleFrame
2008 else
2009 --Delay(2, function () OnFriendshipChanged(nplayer,LocalPlayer:GetFriendStatus(nplayer)) end)
2010 end
2011 nFrame.TitleFrame.Title.Font = 'ArialBold'
2012
2013
2014 nFrame.Parent = ListFrame
2015 nFrame:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nFrame.Size.Y.Scale),0), "Out", "Linear", BASE_TWEEN,true)
2016 UpdateMinimize()
2017 local nentry = {}
2018 nentry['Frame'] = nFrame
2019 nentry['Player'] = nplayer
2020 nentry['ID'] = AddId
2021 AddId = AddId + 1
2022 table.insert(PlayerFrames,nentry)
2023 if #TeamFrames~=0 then
2024
2025 if nplayer.Neutral then
2026 nentry['MyTeam'] = nil
2027 if not NeutralTeam then
2028 AddNeutralTeam()
2029 else
2030 AddPlayerToTeam(NeutralTeam,nentry)
2031 end
2032
2033 else
2034 local addedToTeam=false
2035 for i,tval in ipairs(TeamFrames) do
2036 if tval['MyTeam'].TeamColor == nplayer.TeamColor then
2037 AddPlayerToTeam(tval,nentry)
2038 nentry['MyTeam'] = tval
2039 addedToTeam=true
2040 end
2041 end
2042 if not addedToTeam then
2043 nentry['MyTeam']=nil
2044 if not NeutralTeam then
2045 AddNeutralTeam()
2046 else
2047 AddPlayerToTeam(NeutralTeam,nentry)
2048 end
2049 nentry['MyTeam'] = NeutralTeam
2050 end
2051 end
2052
2053 end
2054
2055 if nplayer:FindFirstChild('leaderstats') then
2056 LeaderstatsAdded(nentry)
2057 end
2058
2059 nplayer.ChildAdded:connect(function(nchild)
2060 if nchild.Name == 'leaderstats' then
2061 while AddingFrameLock do debugprint('in adding leaderstats lock') wait(1/30) end
2062 AddingFrameLock = true
2063 LeaderstatsAdded(nentry)
2064 AddingFrameLock = false
2065 end
2066 end)
2067
2068 nplayer.ChildRemoved:connect(function (nchild)
2069 if nplayer==LocalPlayer and nchild.Name == 'leaderstats' then
2070 LeaderstatsRemoved(nchild,nentry)
2071 end
2072 end)
2073 nplayer.Changed:connect(function(prop)PlayerChanged(nentry,prop) end)
2074
2075 local listener = WaitForChild(nFrame,'ClickListener')
2076 listener.Active = true
2077 listener.MouseButton1Down:connect(function(nx,ny) OnPlayerEntrySelect(nentry, nx,ny) end)
2078
2079 AddMiddleBGFrame()
2080 BaseUpdate()
2081 AddingFrameLock = false
2082end
2083
2084--[[
2085 Note:major optimization can be done here
2086 removes this player's frame if it exists, calls base update
2087--]]
2088function RemovePlayerFrame(tplayer)
2089 while AddingFrameLock do debugprint('in removing player frame lock') wait(1/30) end
2090 AddingFrameLock = true
2091
2092 local tteam
2093 for i,key in ipairs(PlayerFrames) do
2094 if tplayer == key['Player'] then
2095 if PopUpClipFrame.Parent == key['Frame'] then
2096 PopUpClipFrame.Parent = nil
2097 end
2098 key['Frame']:Destroy()
2099 tteam=key['MyTeam']
2100 table.remove(PlayerFrames,i)
2101 end
2102 end
2103 if tteam then
2104 for j,tentry in ipairs(tteam['MyPlayers']) do
2105 if tentry['Player'] == tplayer then
2106 RemovePlayerFromTeam(tteam,j)
2107 end
2108 end
2109 end
2110
2111 RemoveMiddleBGFrame()
2112 UpdateMinimize()
2113 BaseUpdate()
2114 AddingFrameLock = false
2115end
2116
2117Players.ChildRemoved:connect(RemovePlayerFrame)
2118
2119----------------------------
2120-- Team Callback Functions
2121----------------------------
2122--[[
2123 turns a list of team entries with sub lists of players into a single ordered
2124 list, in the correct order,and of the correct length
2125 @Args:
2126 tframes the team entries to unroll
2127 outframes the list to unroll these entries into
2128--]]
2129function UnrollTeams(tframes,outframes)
2130 local numEntries = 0
2131 if NeutralTeam and not NeutralTeam['IsHidden'] then
2132 for i,val in ipairs(NeutralTeam['MyPlayers']) do
2133 numEntries = numEntries + 1
2134 outframes[numEntries] = val['Frame']
2135 end
2136 numEntries = numEntries + 1
2137 outframes[numEntries] = NeutralTeam['Frame']
2138 end
2139 for i,val in ipairs(tframes) do
2140 if not val['IsHidden'] then
2141 for j,pval in ipairs(val.MyPlayers) do
2142 numEntries = numEntries + 1
2143 outframes[numEntries] = pval['Frame']
2144 end
2145 numEntries = numEntries + 1
2146 outframes[numEntries] = val['Frame']
2147 end
2148 end
2149 -- clear any additional entries from outframes
2150 for i = numEntries + 1,#outframes,1 do
2151 outframes[i] = nil
2152 end
2153end
2154--[[
2155 uses lua's table.sort to sort the teams
2156--]]
2157function TeamSortFunc(a,b)
2158 if a['TeamScore'] == b['TeamScore'] then
2159 return a['ID'] < b['ID']
2160 end
2161 if not a['TeamScore'] then return false end
2162 if not b['TeamScore'] then return true end
2163 return a['TeamScore'] < b['TeamScore']
2164
2165end
2166--[[
2167 consider adding lock with wait for performance
2168 sorts each of the team's player lists induvidually, adds up the team scores.
2169 @Args:
2170 tentries table of team entries
2171--]]
2172function SortTeams(tentries)
2173
2174 for i,val in ipairs(tentries) do
2175
2176 table.sort(val['MyPlayers'],PlayerSortFunction)
2177 AddTeamScores(val)
2178 end
2179 table.sort(tentries,TeamSortFunc)
2180end
2181--[[
2182 base update for team mode, adds up the scores of all teams, sorts them,
2183 then unrolls them into middleframes
2184--]]
2185function TeamListModeUpdate()
2186 RecreateScoreColumns(PlayerFrames)
2187 SortTeams(TeamFrames)
2188 if NeutralTeam then
2189 AddTeamScores(NeutralTeam)
2190 --RecreateScoreColumns(NeutralTeam['MyPlayers'])
2191 end
2192 UnrollTeams(TeamFrames,MiddleFrames)
2193end
2194--[[
2195 adds up all the score of this team's players to form the team score
2196 @Args:
2197 team team entry to sum the scores of
2198--]]
2199function AddTeamScores(team)
2200
2201 for j = 1, #ScoreNames,1 do
2202 local i = ScoreNames[j]
2203 local tscore = 0
2204 for _,j in ipairs(team['MyPlayers']) do
2205 local tval = j['Player']:FindFirstChild('leaderstats') and j['Player'].leaderstats:FindFirstChild(i['Name'])
2206 if tval and not tval:IsA('StringValue') then
2207 tscore = tscore + GetScoreValue((j['Player'].leaderstats)[i['Name'] ])
2208 end
2209 end
2210 if team['Frame']:FindFirstChild(i['Name']) then
2211 --team['Frame'][i['Name'] ].Size = UDim2.new(1 - (ScrollBarFrame.Size.X.Scale * 2),- ((j-1) * SpacingPerStat),1,0)
2212 team['Frame'][i['Name'] ].Text = tostring(tscore)
2213 end
2214 end
2215 UpdateMinimize()
2216
2217end
2218
2219--[[
2220 finds previous team this player was on, and if it exists calls removeplayerfromteam
2221 @Args
2222 entry Player entry
2223--]]
2224function FindRemovePlayerFromTeam(entry)
2225 if entry['MyTeam'] then
2226 for j,oldEntry in ipairs(entry['MyTeam']['MyPlayers']) do
2227 if oldEntry['Player'] == entry['Player'] then
2228 RemovePlayerFromTeam(entry['MyTeam'],j)
2229 return
2230 end
2231 end
2232 elseif NeutralTeam then
2233 for j,oldEntry in ipairs(NeutralTeam['MyPlayers']) do
2234 if oldEntry['Player'] == entry['Player'] then
2235 RemovePlayerFromTeam(NeutralTeam,j)
2236 return
2237 end
2238 end
2239 end
2240end
2241--[[
2242 removes a single player from a given team (not usually called directly)
2243 @Args:
2244 teamEntry team entry to remove player from
2245 index index of player in 'MyPlayers' list to remove
2246--]]
2247function RemovePlayerFromTeam(teamEntry,index)
2248 table.remove(teamEntry['MyPlayers'],index)
2249 --if teamEntry['AutoHide'] and #teamEntry['MyPlayers'] == 0 then
2250 if teamEntry==NeutralTeam and #teamEntry['MyPlayers']==0 then
2251 RemoveNeutralTeam()
2252 end
2253end
2254--[[
2255 adds player entry entry to teamentry
2256 removes them from any previous team
2257 @Args:
2258 teamEntry entry of team to add player to
2259 entry player entry to add to this team
2260--]]
2261function AddPlayerToTeam(teamEntry,entry)
2262 FindRemovePlayerFromTeam(entry)
2263 table.insert(teamEntry['MyPlayers'],entry)
2264 entry['MyTeam'] = teamEntry
2265 if teamEntry['IsHidden'] then
2266 teamEntry['Frame'].Parent = ListFrame
2267 AddMiddleBGFrame()
2268 end
2269 teamEntry['IsHidden'] = false
2270end
2271
2272
2273function SetPlayerToTeam(entry)
2274 FindRemovePlayerFromTeam(entry)
2275 -- check to see if team exists, if it does add to that team
2276 local setToTeam = false
2277 for i,tframe in ipairs(TeamFrames) do
2278 -- add my entry on the new team
2279 if tframe['MyTeam'].TeamColor == entry['Player'].TeamColor then
2280 AddPlayerToTeam(tframe,entry)
2281 setToTeam = true
2282 end
2283 end
2284 -- if player was set to an invalid team, then set it back to neutral
2285 if not setToTeam and #(game.Teams:GetTeams())>0 then
2286 debugprint(entry['Player'].Name..'could not find team')
2287 entry['MyTeam']=nil
2288 if not NeutralTeam then
2289 AddNeutralTeam()
2290 else AddPlayerToTeam(NeutralTeam,entry) end
2291 end
2292end
2293
2294--[[
2295 Note:another big one, consiter breaking up
2296 called when any children of player changes
2297 handles 'Neutral', teamColor, Name and MembershipType changes
2298 @Args
2299 entry Player entry changed
2300 property name of property changed
2301--]]
2302function PlayerChanged(entry, property)
2303 while PlayerChangedLock do
2304 debugprint('in playerchanged lock')
2305 wait(1/30)
2306 end
2307 PlayerChangedLock=true
2308 if property == 'Neutral' then
2309 -- if player changing to neutral
2310 if entry['Player'].Neutral and #(game.Teams:GetTeams())>0 then
2311 debugprint(entry['Player'].Name..'setting to neutral')
2312 FindRemovePlayerFromTeam(entry)
2313 entry['MyTeam']=nil
2314 if not NeutralTeam then
2315 debugprint(entry['Player'].Name..'creating neutral team')
2316 AddNeutralTeam()
2317 else
2318 debugprint(entry['Player'].Name..'adding to neutral team')
2319 AddPlayerToTeam(NeutralTeam,entry)
2320 end
2321 elseif #(game.Teams:GetTeams())>0 then -- else player switching to a team, or a weird edgecase
2322 debugprint(entry['Player'].Name..'has been set non-neutral')
2323 SetPlayerToTeam(entry)
2324 end
2325 BaseUpdate()
2326 elseif property == 'TeamColor' and not entry['Player'].Neutral and entry['Player'] ~= entry['MyTeam'] then
2327 debugprint(entry['Player'].Name..'setting to new team')
2328 SetPlayerToTeam(entry)
2329 BaseUpdate()
2330 elseif property == 'Name' or property == 'MembershipType' then
2331 entry['Frame']:FindFirstChild('BCLabel').Image = getMembershipTypeIcon(entry['Player'].MembershipType,entry['Player'].Name)
2332 entry['Frame'].Name = entry['Player'].Name
2333 entry['Frame'].TitleFrame.Title.Text = entry['Player'].Name
2334 if(entry['Frame'].BCLabel.Image ~= '') then
2335 entry['Frame'].TitleFrame.Title.Position=UDim2.new(.01, 30, .1, 0)
2336 end
2337 if entry['Player'] == LocalPlayer then
2338 entry['Frame'].TitleFrame.DropShadow.Text= entry['Player'].Name
2339 ChangeHeaderName(entry['Player'].Name)
2340 end
2341 BaseUpdate()
2342 end
2343 PlayerChangedLock=false
2344end
2345
2346function OnFriendshipChanged(player,friendStatus)
2347
2348 Delay(.5,function()
2349 debugprint('friend status changed for:'..player.Name .." ".. tostring(friendStatus) .. " vs " .. tostring(GetFriendStatus(player)) )
2350 for _, entry in ipairs(PlayerFrames) do
2351 if entry['Player']==player then
2352 local nicon = getFriendStatusIcon(friendStatus)
2353 if nicon == '' and entry['Frame'].FriendLabel.Image ~= '' then
2354 entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position-UDim2.new(0,17,0,0)
2355 elseif nicon ~= '' and entry['Frame'].FriendLabel.Image == '' then
2356 entry['Frame'].TitleFrame.Title.Position=entry['Frame'].TitleFrame.Title.Position+UDim2.new(0,17,0,0)
2357 debugprint('confirmed status:'..player.Name)
2358 end
2359 entry['Frame'].FriendLabel.Image = nicon
2360 return
2361 end
2362 end
2363 end)
2364end
2365
2366--LocalPlayer.FriendStatusChanged:connect(OnFriendshipChanged)
2367
2368--[[
2369 adds a neutral team if nessisary
2370 Note: a lot of redundant code here, might want to refactor to share a function with insertteamframe
2371--]]
2372function AddNeutralTeam()
2373 while NeutralTeamLock do debugprint('in neutral team 2 lock') wait() end
2374 NeutralTeamLock = true
2375
2376 local defaultTeam = Instance.new('Team')
2377 defaultTeam.TeamColor = BrickColor.new('White')
2378 defaultTeam.Name = 'Neutral'
2379 local nentry = {}
2380 nentry['MyTeam'] = defaultTeam
2381 nentry['MyPlayers'] = {}
2382 nentry['Frame'] = MiddleTemplate:Clone()
2383 WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = defaultTeam.Name
2384 nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0)
2385 nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0)
2386 nentry['Frame'].TitleFrame.Title.Font = 'ArialBold'
2387
2388 nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0)
2389 WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(function(nx,ny) StartDrag(nentry,nx,ny) end)
2390 nentry['Frame'].ClickListener.BackgroundColor3 = BrickColor.new("Black").Color
2391 nentry['Frame'].ClickListener.BackgroundTransparency = .7
2392 nentry['Frame'].ClickListener.AutoButtonColor=false
2393 nentry['AutoHide'] = true
2394 nentry['IsHidden'] = true
2395 for _,i in pairs(PlayerFrames) do
2396 if i['Player'].Neutral or not i['MyTeam'] then
2397 AddPlayerToTeam(nentry,i)
2398 end
2399 end
2400 if #nentry['MyPlayers'] > 0 then
2401 NeutralTeam = nentry
2402 UpdateMinimize()
2403 BaseUpdate()
2404 end
2405 NeutralTeamLock = false
2406end
2407
2408function RemoveNeutralTeam()
2409 while NeutralTeamLock do debugprint('in neutral team lock') wait() end
2410 NeutralTeamLock = true
2411 NeutralTeam['Frame']:Destroy()
2412 NeutralTeam=nil
2413 RemoveMiddleBGFrame()
2414 NeutralTeamLock = false
2415end
2416
2417--[[
2418
2419--]]
2420function TeamScoreChanged(entry,nscore)
2421 WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nscore)
2422 entry['TeamScore'] = nscore
2423end
2424--[[
2425 called when child added to a team, used for autohide functionality
2426 Note: still has teamscore, consiter removing
2427--]]
2428function TeamChildAdded(entry,nchild)
2429 if nchild.Name == 'AutoHide' then
2430 entry['AutoHide'] = true
2431 elseif nchild.Name == 'TeamScore' then
2432 WaitForChild(entry['Frame'],'PlayerScore').Text = tostring(nchild.Value)
2433 entry['TeamScore'] = nchild.Value
2434 nchild.Changed:connect(function() TeamScoreChanged(entry,nchild.Value) end)
2435 end
2436end
2437--[[
2438 called when child added to a team, used for autohide functionality
2439 Note: still has teamscore, consiter removing
2440--]]
2441function TeamChildRemoved(entry,nchild)
2442 if nchild.Name == 'AutoHide' then
2443 entry['AutoHide'] = false
2444 elseif nchild.Name == 'TeamScore' then
2445 WaitForChild(entry['Frame'],'PlayerScore').Text = ""
2446 entry['TeamScore'] = nil
2447 end
2448end
2449
2450function TeamChanged(entry, property)
2451 if property=='Name' then
2452 WaitForChild(WaitForChild(entry['Frame'],'TitleFrame'),'Title').Text = entry['MyTeam'].Name
2453
2454 elseif property=='TeamColor' then
2455 nentry['Frame'].TitleFrame.Title.TextColor3 = nentry['MyTeam'].TeamColor.Color
2456
2457 for _,i in pairs(TeamFrames) do
2458 if i['MyTeam'].TeamColor == entry['MyTeam'] then
2459 RemoveTeamFrame(entry['MyTeam']) --NO DUPLICATE TEAMS!
2460 end
2461 end
2462
2463 entry['MyPlayers']={}
2464
2465 for _,i in pairs(PlayerFrames) do
2466 SetPlayerToTeam(i)
2467 end
2468 BaseUpdate()
2469 end
2470end
2471
2472--[[
2473 creates team entry and frame for this team, sets up listeners for this team
2474 adds any players intended for this team,Creates neutral team if this is the first team added
2475 Note:might be best to break this into multiple functions to simplify
2476 @Args:
2477 nteam new team object added
2478--]]
2479function InsertTeamFrame(nteam)
2480 while AddingFrameLock do debugprint('in adding team frame lock') wait(1/30) end
2481 AddingFrameLock = true
2482 --for _,i in pairs(TeamFrames) do
2483 local nentry = {}
2484 nentry['MyTeam'] = nteam
2485 nentry['MyPlayers'] = {}
2486 nentry['Frame'] = MiddleTemplate:Clone()
2487 WaitForChild(WaitForChild(nentry['Frame'],'TitleFrame'),'Title').Text = nteam.Name
2488 nentry['Frame'].TitleFrame.Title.Font = 'ArialBold'
2489 nentry['Frame'].TitleFrame.Title.FontSize = 'Size18'
2490 nentry['Frame'].TitleFrame.Title.TextColor3 = nentry['MyTeam'].TeamColor.Color
2491 nentry['Frame'].BackgroundColor3 = BrickColor.new("Black").Color
2492 nentry['Frame'].BackgroundColor3 = BrickColor.new("Black").Color
2493
2494 nentry['Frame'].TitleFrame.Position=UDim2.new(nentry['Frame'].TitleFrame.Position.X.Scale,nentry['Frame'].TitleFrame.Position.X.Offset,.1,0)
2495 nentry['Frame'].TitleFrame.Size=UDim2.new(nentry['Frame'].TitleFrame.Size.X.Scale,nentry['Frame'].TitleFrame.Size.X.Offset,.8,0)
2496 nentry['Frame'].Position = UDim2.new(1,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0)
2497 WaitForChild(nentry['Frame'],'ClickListener').MouseButton1Down:connect(function(nx,ny) StartDrag(nentry,nx,ny) end)
2498 nentry['Frame'].ClickListener.BackgroundColor3 = BrickColor.new("Black").Color
2499 nentry['Frame'].ClickListener.BackgroundTransparency = .7
2500 nentry['Frame'].ClickListener.AutoButtonColor=false
2501 AddId = AddId + 1
2502 nentry['ID'] = AddId
2503 nentry['AutoHide'] = false
2504 if nteam:FindFirstChild('AutoHide') then
2505 nentry['AutoHide'] = true
2506 end
2507 if nteam:FindFirstChild('TeamScore') then
2508 TeamChildAdded(nentry,nteam.TeamScore)
2509
2510 end
2511
2512 nteam.ChildAdded:connect(function(nchild) TeamChildAdded(nentry,nchild) end)
2513 nteam.ChildRemoved:connect(function(nchild) TeamChildRemoved(nentry,nchild) end)
2514 nteam.Changed:connect(function(prop) TeamChanged(nentry,prop) end)
2515
2516 for _,i in pairs(PlayerFrames) do
2517 if not i['Player'].Neutral and i['Player'].TeamColor == nteam.TeamColor then
2518 AddPlayerToTeam(nentry,i)
2519 end
2520 end
2521 nentry['IsHidden'] = false
2522 if not nentry['AutoHide'] or #nentry['MyPlayers'] > 0 then
2523
2524 nentry['Frame'].Parent = ListFrame
2525 nentry['Frame']:TweenPosition(UDim2.new(.5,0,((#MiddleFrames) * nentry['Frame'].Size.Y.Scale),0), "Out", "Linear", BASE_TWEEN,true)
2526 AddMiddleBGFrame()
2527 else
2528 nentry['IsHidden'] = true
2529 nentry['Frame'].Parent = nil
2530 end
2531
2532 table.insert(TeamFrames,nentry)
2533 UpdateMinimize()
2534 BaseUpdate()
2535 if #TeamFrames == 1 and not NeutralTeam then
2536 AddNeutralTeam()
2537 end
2538 AddingFrameLock = false
2539end
2540--[[
2541 removes team from team list
2542 @Args:
2543 nteam Teamobject to remove
2544--]]
2545function RemoveTeamFrame(nteam)
2546 while AddingFrameLock do debugprint('in removing team frame lock') wait(1/30) end
2547 AddingFrameLock = true
2548 if IsMinimized.Value then
2549 end
2550 local myEntry
2551 for i,key in ipairs(TeamFrames) do
2552 if nteam == key['MyTeam'] then
2553 myEntry = key
2554 key['Frame']:Destroy()
2555 table.remove(TeamFrames,i)
2556 end
2557 end
2558 if #TeamFrames==0 then
2559 debugprint('removeteamframe, remove neutral')
2560 if NeutralTeam then
2561 RemoveNeutralTeam()
2562 end
2563 end
2564 for i,key in ipairs(myEntry['MyPlayers']) do
2565 RemovePlayerFromTeam(myEntry,i)
2566 PlayerChanged(key, 'TeamColor')
2567 end
2568 RemoveMiddleBGFrame()
2569 BaseUpdate()
2570 AddingFrameLock = false
2571end
2572
2573function TeamAdded(nteam)
2574 InsertTeamFrame(nteam)
2575end
2576
2577function TeamRemoved(nteam)
2578 RemoveTeamFrame(nteam)
2579end
2580 ---------------------------------
2581--[[
2582 called when ANYTHING changes the state of the playerlist
2583 re-sorts everything,assures correct positions of all elements
2584--]]
2585function BaseUpdate()
2586 while BaseUpdateLock do debugprint('in baseupdate lock') wait(1/30) end
2587 BaseUpdateLock = true
2588 --print ('baseupdate')
2589 UpdateStatNames()
2590
2591 if #TeamFrames == 0 and not NeutralTeam then
2592 PlayerListModeUpdate()
2593 else
2594 TeamListModeUpdate()
2595 end
2596 for i,key in ipairs(MiddleFrames) do
2597 if key.Parent ~= nil then
2598 key:TweenPosition(UDim2.new(.5,0,((#MiddleFrames - (i)) * key.Size.Y.Scale),0), "Out", "Linear", BASE_TWEEN,true)
2599 end
2600 end
2601 if not IsMinimized.Value and #MiddleFrames>DefaultEntriesOnScreen then
2602 UpdateScrollPosition()
2603 end
2604
2605 UpdateMinimize()
2606
2607 UpdateScrollBarSize()
2608 UpdateScrollPosition()
2609
2610 UpdateScrollBarVisibility()
2611 --debugprint('EndBaseUpdate')
2612 BaseUpdateLock = false
2613end
2614
2615--[[
2616 code for attaching tab key to maximizing player list
2617--]]
2618--game.GuiService:AddKey("\t")
2619local LastTabTime = time()
2620Mouse.KeyDown:connect(
2621function(key)
2622 if key == "\t" then
2623 debugprint('caught tab key')
2624 local modalCheck, isModal = pcall(function() return game.GuiService.IsModalDialog end)
2625 if modalCheck == false or (modalCheck and isModal == false) then
2626 if time() - LastTabTime > 0.4 then
2627 LastTabTime = time()
2628 if IsTabified.Value then
2629 if not IsMaximized.Value then
2630 ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Linear',BASE_TWEEN*1.2,true)
2631 IsMaximized.Value = true
2632 else
2633 ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Linear',BASE_TWEEN*1.2,true)
2634 IsMaximized.Value = false
2635 IsMinimized.Value=true
2636 end
2637 else
2638 ToggleMaximize()
2639 end
2640
2641 end
2642 end
2643 end
2644end)
2645
2646
2647function PlayersChildAdded(tplayer)
2648 if tplayer:IsA('Player') then
2649 Spawn(function() debugPlayerAdd(tplayer) end)
2650 else
2651 BlowThisPopsicleStand()
2652 end
2653end
2654
2655function coreGuiChanged(coreGuiType, enabled)
2656-- if coreGuiType == Enum.CoreGuiType.All or coreGuiType == Enum.CoreGuiType.PlayerList then
2657-- MainFrame.Visible = enabled
2658-- end
2659end
2660
2661function TeamsChildAdded(nteam)
2662 if nteam:IsA('Team') then
2663 TeamAdded(nteam)
2664 else
2665 BlowThisPopsicleStand()
2666 end
2667end
2668
2669function TeamsChildRemoved(nteam)
2670 if nteam:IsA('Team') then
2671 TeamRemoved(nteam)
2672 else
2673 BlowThisPopsicleStand()
2674 end
2675end
2676
2677 ----------------------------
2678 -- Hookups and initialization
2679 ----------------------------
2680function debugPlayerAdd(p)
2681 InsertPlayerFrame(p)
2682end
2683
2684pcall(function()
2685 coreGuiChanged(Enum.CoreGuiType.PlayerList, Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.PlayerList))
2686 Game.StarterGui.CoreGuiChangedSignal:connect(coreGuiChanged)
2687end)
2688
2689while not game:GetService('Teams') do wait(1/30) debugprint('Waiting For Teams') end
2690for _,i in pairs(game.Teams:GetTeams()) do TeamAdded(i) end
2691for _,i in pairs(Players:GetPlayers()) do Spawn(function() debugPlayerAdd(i) end) end
2692
2693game.Teams.ChildAdded:connect(TeamsChildAdded)
2694game.Teams.ChildRemoved:connect(TeamsChildRemoved)
2695Players.ChildAdded:connect(PlayersChildAdded)
2696
2697InitReportAbuse()
2698AreNamesExpanded.Value = true
2699BaseUpdate()
2700
2701
2702
2703--UGGGLY,find a better way later
2704--wait(2)
2705IsPersonalServer= not not game.Workspace:FindFirstChild("PSVariable")
2706
2707 ----------------------------
2708 -- Running Logic
2709 ----------------------------
2710
2711 --debug stuffs, will only run for 'newplayerlistisbad'
2712 if LocalPlayer.Name == 'newplayerlistisbad' or LocalPlayer.Name == 'imtotallyadmin' then
2713 debugFrame.Parent = ScreenGui
2714 Spawn(function()
2715 while true do
2716 local str_players=''
2717 for _,i in pairs(game.Players:GetPlayers()) do
2718 str_players= str_players .." " .. i.Name
2719 end
2720 debugplayers.Text=str_players
2721 wait(.5)
2722 end
2723 end)
2724 end