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