· 8 years ago · Feb 15, 2018, 07:28 PM
1--rbxsig%XfnLm/J5UJPgY4w4rg5qSydaeJOURqgvB5GxT/HsDw2KXQcj/u0MpAvusliq62Tmau/KgW5m6mfTkhybYvG/2l7XDjR/PrZR9nQ323B6UYixjNgqMAmCf3eEDSxKz1GG6CuuwLZ6cE8dST7r0s0suJBgj3zbwi7AwRL0QTuR2FI=%
2--rbxassetid%48488235%
3--------------------
4-- Super Util
5--------------------
6
7local ADMINS =
8{
9 rbadam = 1,
10 adamintygum = 1,
11 androidtest = 1,
12 robloxfrenchie = 1,
13 jackssmirkingrevenge = 1,
14 lindapepita = 1,
15 vaiobot = 1,
16 goddessnoob = 1,
17 effward = 1,
18 blockhaak = 1,
19 drewbda = 1,
20 ['errorerror1234'] = 1,
21 tone = 1,
22 fasterbuilder19 = 1,
23 zeuxcg = 1,
24 concol2 = 1,
25 reesemcblox = 1,
26 jeditkacheff = 'http://www.roblox.com/asset/?id=134032333',
27 whkm1980 = 1,
28 chiefjustus = 1,
29 ellissar = 1,
30 arbolito = 1,
31 noob007 = 1,
32 limon = 1,
33 cmed = 1,
34 hawkington = 1,
35 tabemono = 1,
36 autoconfig = 1,
37 brighteyes = 1,
38 monsterinc3d = 1,
39 mrdoombringer = 1,
40 isolatedevent = 1,
41 countonconnor = 1,
42 scubasomething = 1,
43 onlytwentycharacters = 1,
44 lordrugdumph = 1,
45 bellavour = 1,
46 ['david.baszucki'] = 1,
47 ibanez2189 = 1,
48 sorcus = 'http://www.roblox.com/asset/?id=113059239',
49 deeana00 = 1,
50 thelorekt = 1,
51 niquemonster = 1,
52 thorasaur = 1,
53 ['mse6'] = 1,
54 corgiparade = 1,
55 varia = 1,
56 ['4runningwolves'] = 1,
57 pulmoesflor = 1,
58 olive71 = 1,
59 groundcontroll2 = 1,
60 gurukrish = 1,
61 countvelcro = 1,
62 iltalumi = 1,
63 juanjuan23 = 1,
64 ostrichsized = 1,
65 jackintheblox = 1,
66 slingshotjunkie = 1,
67 gordonrox24 = 1,
68 sharpnine = 1,
69 motornerve = 1,
70 motornerve = 1,
71 watchmedogood = 1,
72 jmargh = 1,
73 jaykorean = 1,
74 foyle = 1,
75 majortom4321 = 1,
76 shedletsky = 'http://www.roblox.com/asset/?id=105897927',
77 supernovacaine = 1,
78 ffjosh = 1,
79 sickenedmonkey = 1,
80 doughtless = 1,
81 kbux = 1,
82 totallynothere = 1,
83 erzastar = 1,
84 keith = 1,
85 chro = 1,
86 solarcrane = 1,
87 glorioussalt = 1,
88 uristmcsparks = 1,
89 itolauren = 1,
90 malcomso = 1,
91 stickmasterluke = 1,
92 windlight13 = 1,
93 yumyumcheerios = 1,
94 stravant = 1,
95 byteme = 1,
96 imaginationsensation = 1,
97 ['matt.dusek'] = 1,
98 mcrtest = 1,
99 seranok = 1,
100 maxvee = 1,
101 coatp0cketninja = 1,
102 screenme = 1,
103 b1tsh1ft = 1,
104 totbl = 1,
105 aquabot8 = 1,
106 grossinger = 1,
107 merely = 1,
108 cdakkar = 1,
109 siekiera = 1,
110 robloxkidsaccount = 1,
111 flotsamthespork = 1,
112 soggoth = 1,
113 phil = 1,
114 orcasparkles = 1,
115 skullgoblin = 1,
116 rickrosstheb0ss = 1,
117 argonpirate = 1,
118 nobledragon = 1,
119 squidcod = 1,
120 raeglyn = 1,
121 robloxsai = 'http://www.roblox.com/asset/?id=161078086',
122 briarroze = 1,
123 hawkeyebandit = 1,
124 dapperbuffalo = 1,
125 vukota = 1,
126 swiftstone = 1,
127 gemlocker = 1,
128 loopylens = 1,
129 tarabyte = 1,
130 timobius = 1,
131 tobotrobot = 1,
132 foster008 = 1,
133 twberg = 1,
134 darthvaden = 1,
135 khanovich = 1,
136 codewriter = 1,
137 vladthefirst = 1,
138 phaedre = 1,
139 gorroth = 1,
140 sphinxshen = 1,
141 jynj1984 = 1,
142 roboyz = 1,
143 zodiaczak = 1,
144}
145
146
147
148local Images = {
149 bottomDark = '94691904',
150 bottomLight = '94691940',
151 midDark = '94691980',
152 midLight = '94692025',
153 LargeDark = '96098866',
154 LargeLight = '96098920',
155 LargeHeader = '96097470',
156 NormalHeader = '94692054',
157 LargeBottom = '96397271',
158 NormalBottom = '94754966',
159 DarkBluePopupMid = '97114905',
160 LightBluePopupMid = '97114905',
161 DarkPopupMid = '97112126',
162 LightPopupMid = '97109338',
163 DarkBluePopupTop = '97114838',
164 DarkBluePopupBottom = '97114758',
165 DarkPopupBottom = '100869219',
166 LightPopupBottom = '97109175',
167}
168
169local BASE_TWEEN = .25
170
171local MOUSE_HOLD_TIME = .15
172local MOUSE_DRAG_DISTANCE = 15
173
174--[[
175 Generic object Create function, which I am using to create Gui's
176 Thanks to Stravant!
177--]]
178local Obj = {}
179function Obj.Create(guiType)
180 return function(data)
181 local obj = Instance.new(guiType)
182 for k, v in pairs(data) do
183 if type(k) == 'number' then
184 v.Parent = obj
185 else
186 obj[k] = v
187 end
188 end
189 return obj
190 end
191end
192
193--[[
194 makes a full sized background for a guiobject
195 @Args:
196 imgName asset name of image to fill background
197 @Return: background gui object
198--]]
199function MakeBackgroundGuiObj(imgName)
200 return Obj.Create'ImageLabel'
201 {
202 Name = 'Background',
203 BackgroundTransparency = 1,
204 Image = imgName,
205 Position = UDim2.new(0, 0, 0, 0),
206 Size = UDim2.new(1,0,1,0),
207 }
208end
209--[[ turns 255 integer color value to a color3 --]]
210function Color3I(r,g,b)
211 return Color3.new(r/255,g/255,b/255)
212end
213
214--[[
215 Gets correct icon for builder's club status to display by name
216 @Args:
217 membershipType Enum of membership status
218 @Return: string of image asset
219--]]
220function getMembershipTypeIcon(membershipType,playerName)
221 if ADMINS[string.lower(playerName)]~=nil then
222 if ADMINS[string.lower(playerName)] == 1 then
223 return "http://www.roblox.com/asset/?id=99727663"
224 else
225 return ADMINS[string.lower(playerName)]
226 end
227 elseif membershipType == Enum.MembershipType.None then
228 return ""
229 elseif membershipType == Enum.MembershipType.BuildersClub then
230 return "rbxasset://textures/ui/TinyBcIcon.png"
231 elseif membershipType == Enum.MembershipType.TurboBuildersClub then
232 return "rbxasset://textures/ui/TinyTbcIcon.png"
233 elseif membershipType == Enum.MembershipType.OutrageousBuildersClub then
234 return "rbxasset://textures/ui/TinyObcIcon.png"
235 else
236 error("Unknown membershipType" .. membershipType)
237 end
238end
239
240local function getFriendStatusIcon(friendStatus)
241 if friendStatus == Enum.FriendStatus.Unknown or friendStatus == Enum.FriendStatus.NotFriend then
242 return ""
243 elseif friendStatus == Enum.FriendStatus.Friend then
244 return "http://www.roblox.com/asset/?id=99749771"
245 elseif friendStatus == Enum.FriendStatus.FriendRequestSent then
246 return "http://www.roblox.com/asset/?id=99776888"
247 elseif friendStatus == Enum.FriendStatus.FriendRequestReceived then
248 return "http://www.roblox.com/asset/?id=99776838"
249 else
250 error("Unknown FriendStatus: " .. friendStatus)
251 end
252end
253
254
255--[[
256 Utility function to create buttons for the popup menus
257 @Args:
258 nparent what to parent this button to
259 ntext text to put on this button
260 index number index of this entry in menu
261 last is this the last element of the popup menu
262 @Return: a popup menu button
263--]]
264function MakePopupButton(nparent,ntext,index,last)
265 local tobj = Obj.Create"ImageButton"
266 {
267 Name = 'ReportButton',
268 BackgroundTransparency = 1,
269 Position = UDim2.new(0,0,1*index,0),
270 Size = UDim2.new(1, 0, 1, 0),
271 ZIndex=7,
272 Obj.Create'TextLabel'
273 {
274 Name = 'ButtonText',
275 BackgroundTransparency = 1,
276 Position = UDim2.new(.07, 0, .07, 0),
277 Size = UDim2.new(.86,0,.86,0),
278 Parent = HeaderFrame,
279 Font = 'ArialBold',
280 Text = ntext,
281 FontSize = 'Size14',
282 TextScaled = true,
283 TextColor3 = Color3.new(1,1,1),
284 TextStrokeTransparency = 1,
285 ZIndex=7,
286 },
287 Parent = nparent,
288 }
289 if index==0 then
290 tobj.Image = 'http://www.roblox.com/asset/?id=97108784'
291 elseif last then
292 if index%2==1 then
293 tobj.Image = 'http://www.roblox.com/asset/?id='.. Images['LightPopupBottom']
294 else
295 tobj.Image = 'http://www.roblox.com/asset/?id='.. Images['DarkPopupBottom']
296 end
297 else
298 if index%2==1 then
299 tobj.Image = 'http://www.roblox.com/asset/?id=97112126'
300 else
301 tobj.Image = 'http://www.roblox.com/asset/?id=97109338'
302 end
303 end
304 return tobj
305end
306
307
308--[[
309 obligatory wait for child function
310 @Args:
311 parent Parent object to look for child in
312 child name of child object to look for
313 @Return: object waited for
314--]]
315function WaitForChild(parent,child)
316 while not parent:FindFirstChild(child) do
317 wait() debugprint(" child "..parent.Name.." waiting for "..child)
318 end
319 return parent[child]
320end
321
322 ---------------------------
323 -- Workspace Objects
324 ---------------------------
325
326-- might want to move all this to an init function, wait for localplayer elsewhere
327local Players = game:GetService('Players')
328-- make sure this doesn't run on the server(it will if you dont do this)
329while not Players.LocalPlayer do
330 Players.Changed:wait()
331end
332
333local LocalPlayer = Players.LocalPlayer
334local Mouse = LocalPlayer:GetMouse()
335
336local ScreenGui = Obj.Create"Frame"
337{
338 Name = 'PlayerListScreen',
339 Size = UDim2.new(1, 0, 1, 0),
340 BackgroundTransparency = 1,
341 Parent = script.Parent
342}
343local MainFrame = Obj.Create"Frame"
344{
345 Name = 'LeaderBoardFrame',
346 Position = UDim2.new(1, -150, 0.005, 0),
347 Size = UDim2.new(0, 150, 0, 800),
348 BackgroundTransparency = 1,
349 Parent = ScreenGui,
350}
351
352--frame used for expanding leaderstats when frame is 'focused'
353local FocusFrame = Obj.Create"Frame"
354{
355 Name = 'FocusFrame',
356 Position = UDim2.new(0, 0, 0, 0),
357 Size = UDim2.new(1, 0, 0, 100),
358 BackgroundTransparency = 1,
359 Active = true,
360 Parent = MainFrame,
361}
362
363local TemplateFrameYSize = 0.670000017
364
365 -- HEADER
366local HeaderFrame = Obj.Create"Frame"
367{
368 Name = 'Header',
369 BackgroundTransparency = 1,
370 Position = UDim2.new(0,0,0,0),
371 Size = UDim2.new(1, 0, .07, 0),
372 Parent = MainFrame,
373 MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94692054'),
374}
375 local HeaderFrameHeight = HeaderFrame.Size.Y.Scale
376 local MaximizeButton = Obj.Create"ImageButton"
377 {
378 Name = 'MaximizeButton',
379 Active = true,
380 BackgroundTransparency = 1,
381 Position = UDim2.new(0, 0, 0, 0),
382 Size = UDim2.new(1,0,1,0),
383 Parent = HeaderFrame,
384 }
385 local HeaderName = Obj.Create"TextLabel"
386 {
387 Name = 'PlayerName',
388 BackgroundTransparency = 1,
389 Position = UDim2.new(0, 0, .01, 0),
390 Size = UDim2.new(.98,0,.38,0),
391 Parent = HeaderFrame,
392 Font = 'ArialBold',
393 Text = LocalPlayer.Name,
394 FontSize='Size24',
395 --TextScaled = true,
396 TextColor3 = Color3.new(1,1,1),
397 TextStrokeColor3 = Color3.new(0,0,0),
398 TextStrokeTransparency = 0,
399 TextXAlignment = 'Right',
400 TextYAlignment = 'Center',
401 }
402 local HeaderScore = Obj.Create"TextLabel"
403 {
404 Name = 'PlayerScore',
405 BackgroundTransparency = 1,
406 Position = UDim2.new(0, 0, .4, 0),
407 Size = UDim2.new(.98,0,0,30),
408 Parent = HeaderFrame,
409 Font = 'ArialBold',
410 Text = '',
411 FontSize='Size24',
412 TextYAlignment = 'Top',
413 --TextScaled = true,
414 TextColor3 = Color3.new(1,1,1),
415 TextStrokeTransparency = 1,
416 TextXAlignment = 'Right',
417 TextYAlignment = 'Top',
418 }
419 -- BOTTOM
420 --used for shifting bottom frame for mouse over effects
421local BottomShiftFrame = Obj.Create"Frame"
422{
423 Name= 'BottomShiftFrame',
424 BackgroundTransparency = 1,
425 Position = UDim2.new(0,0,HeaderFrameHeight,0),
426 Size = UDim2.new(1,0,1,0),
427 Parent=MainFrame,
428}
429 local BottomFrame = Obj.Create"Frame"
430 {
431 Name = 'Bottom',
432 BackgroundTransparency = 1,
433 Position = UDim2.new(0,0,.07,0),
434 Size = UDim2.new(1, 0, .03, 0),
435 Parent = BottomShiftFrame,
436 MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94754966'),
437 }
438 local ExtendButton = Obj.Create"ImageButton"
439 {
440 Name = 'bigbutton',
441 Active = true,
442 BackgroundTransparency = 1,
443 Position = UDim2.new(0, 0, 0, 0),
444 Size = UDim2.new(1,0,1.5,0),
445 ZIndex = 3,
446 Parent = BottomFrame,
447 }
448 local ExtendTab = Obj.Create"ImageButton"
449 {
450 Name = 'extendTab',
451 Active = true,
452 BackgroundTransparency = 1,
453 Image = 'http://www.roblox.com/asset/?id=94692731',
454 Position = UDim2.new(.608, 0, .3, 0),
455 Size = UDim2.new(.3,0,.7,0),
456 Parent = BottomFrame,
457 }
458local TopClipFrame = Obj.Create"Frame"
459{
460 Name = 'ListFrame',
461 BackgroundTransparency = 1,
462 Position = UDim2.new(-1,0,.07,0),
463 Size = UDim2.new(2, 0, 1, 0),
464 Parent = MainFrame,
465 ClipsDescendants = true,
466}
467 local BottomClipFrame = Obj.Create"Frame"
468 {
469 Name = 'BottomFrame',
470 BackgroundTransparency = 1,
471 Position = UDim2.new(0,0, - .8,0),
472 Size = UDim2.new(1, 0, 1, 0),
473 Parent = TopClipFrame,
474 ClipsDescendants = true,
475 }
476 local ScrollBarFrame = Obj.Create"Frame"
477 {
478 Name = 'ScrollBarFrame',
479 BackgroundTransparency = 1,
480 Position = UDim2.new(.987,0,.8,0),
481 Size = UDim2.new(.01, 0, .2, 0),
482 Parent = BottomClipFrame,
483 }
484 local ScrollBar = Obj.Create"Frame"
485 {
486 Name = 'ScrollBar',
487 BackgroundTransparency = 0,
488 BackgroundColor3 = Color3.new(.2,.2,.2),
489 Position = UDim2.new(0,0,0,0),
490 Size = UDim2.new(1, 0, .5, 0),
491 ZIndex = 5,
492 Parent = ScrollBarFrame,
493
494 }
495 local ListFrame = Obj.Create"Frame"
496 {
497 Name = 'SubFrame',
498 BackgroundTransparency = 1,
499 Position = UDim2.new(0,0,.8,0),
500 Size = UDim2.new(1, 0, 1, 0),
501 Parent = BottomClipFrame,
502 }
503local PopUpClipFrame = Obj.Create"Frame"
504{
505 Name = 'PopUpFrame',
506 BackgroundTransparency = 1,
507 SizeConstraint='RelativeXX',
508 Position = MainFrame.Position + UDim2.new( 0,-150,0,0),
509 Size = UDim2.new(0,150,0,800),
510 Parent = MainFrame,
511 ClipsDescendants = true,
512 ZIndex=7,
513}
514local PopUpPanel = nil
515 local PopUpPanelTemplate = Obj.Create"Frame"
516 {
517 Name = 'Panel',
518 BackgroundTransparency = 1,
519 Position = UDim2.new(1,0,0,0),
520 Size = UDim2.new(1,0,.032,0),
521 Parent = PopUpClipFrame,
522 }
523
524local StatTitles = Obj.Create"Frame"
525{
526 Name = 'StatTitles',
527 BackgroundTransparency = 1,
528 Position = UDim2.new(0,0,1,-10),
529 Size = UDim2.new(1, 0, 0, 0),
530 Parent = HeaderFrame,
531}
532
533local IsMinimized = Instance.new('BoolValue')
534local IsMaximized = Instance.new('BoolValue')
535local IsTabified = Instance.new('BoolValue')
536local AreNamesExpanded = Instance.new('BoolValue')
537
538
539local MiddleTemplate = Obj.Create"Frame"
540{
541 Name = 'MidTemplate',
542 BackgroundTransparency = 1,
543 Position = UDim2.new(100,0,.07,0),
544 Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0),
545 Obj.Create'ImageLabel'
546 {
547 Name = 'BCLabel',
548 Active = true,
549 BackgroundTransparency = 1,
550 Position = UDim2.new(.005, 5, .20, 0),
551 Size = UDim2.new(0,16,0,16),
552 SizeConstraint = 'RelativeYY',
553 Image = "",
554 ZIndex = 3,
555 },
556 Obj.Create'ImageLabel'
557 {
558 Name = 'FriendLabel',
559 Active = true,
560 BackgroundTransparency = 1,
561 Position = UDim2.new(.005, 5, .15, 0),
562 Size = UDim2.new(0,16,0,16),
563 SizeConstraint = 'RelativeYY',
564 Image = "",
565 ZIndex = 3,
566 },
567 Obj.Create"ImageButton"
568 {
569 Name = 'ClickListener',
570 Active = true,
571 BackgroundTransparency = 1,
572 Position = UDim2.new(.005, 1, 0, 0),
573 Size = UDim2.new(.96,0,1,0),
574 ZIndex = 3,
575 },
576 Obj.Create"Frame"
577 {
578 Name = 'TitleFrame',
579 BackgroundTransparency = 1,
580 Position = UDim2.new(.01, 0, 0, 0),
581 Size = UDim2.new(0,140,1,0),
582 ClipsDescendants=true,
583 Obj.Create"TextLabel"
584 {
585 Name = 'Title',
586 BackgroundTransparency = 1,
587 Position = UDim2.new(0, 5, 0, 0),
588 Size = UDim2.new(100,0,1,0),
589 Font = 'Arial',
590 FontSize='Size14',
591 TextColor3 = Color3.new(1,1,1),
592 TextXAlignment = 'Left',
593 TextYAlignment = 'Center',
594 ZIndex = 3,
595 },
596 },
597
598 Obj.Create"TextLabel"
599 {
600 Name = 'PlayerScore',
601 BackgroundTransparency = 1,
602 Position = UDim2.new(0, 0, 0, 0),
603 Size = UDim2.new(1,0,1,0),
604 Font = 'ArialBold',
605 Text = '',
606 FontSize='Size14',
607 TextColor3 = Color3.new(1,1,1),
608 TextXAlignment = 'Right',
609 TextYAlignment = 'Center',
610 ZIndex = 3,
611 },
612 --Obj.Create'IntValue'{Name = 'ID'},
613 --Obj.Create'ObjectValue'{Name = 'Player'},
614 --Obj.Create'IntValue'{Name = 'Score'},
615 ZIndex = 3,
616}
617local MiddleBGTemplate = Obj.Create"Frame"
618{
619 Name = 'MidBGTemplate',
620 BackgroundTransparency = 1,
621 Position = UDim2.new(100,0,.07,0),
622 Size = UDim2.new(.5, 0, .025, 0),--UDim2.new(1, 0, .03, 0),
623 MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=94692025'),
624
625}
626
627 -- REPORT ABUSE OBJECTS
628
629local ReportAbuseShield = Obj.Create"TextButton"
630{
631 Name = "ReportAbuseShield",
632 Text = "",
633 AutoButtonColor = false,
634 Active = true,
635 Visible = true,
636 Size = UDim2.new(1,0,1,0),
637 BackgroundColor3 = Color3I(51,51,51),
638 BorderColor3 = Color3I(27,42,53),
639 BackgroundTransparency = 1,
640}
641
642local ReportAbuseFrame = Obj.Create "Frame"
643{
644 Name = "Settings",
645 Position = UDim2.new(0.5, - 250, 0.5, - 200),
646 Size = UDim2.new(0.0, 500, 0.0, 400),
647 BackgroundTransparency = 1,
648 Active = true,
649 Parent = ReportAbuseShield,
650}
651
652local AbuseSettingsFrame = Obj.Create"Frame"
653{
654 Name = "ReportAbuseStyle",
655 Size = UDim2.new(1, 0, 1, 0),
656 Active = true,
657 BackgroundTransparency = 1,
658 MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96488767'), -- 96480351'),
659 Obj.Create"TextLabel"
660 {
661 Name = "Title",
662 Text = "Report Abuse",
663 TextColor3 = Color3I(221,221,221),
664 Position = UDim2.new(0.5, 0, 0, 30),
665 Font = Enum.Font.ArialBold,
666 FontSize = Enum.FontSize.Size36,
667 },
668 Obj.Create"TextLabel"
669 {
670 Name = "Description",
671 Text = "This will send a complete report to a moderator. The moderator will review the chat log and take appropriate action.",
672 TextColor3 = Color3I(221,221,221),
673 Position = UDim2.new(.01, 0, 0, 55),
674 Size = UDim2.new(.99, 0, 0, 40),
675 BackgroundTransparency = 1,
676 Font = Enum.Font.Arial,
677 FontSize = Enum.FontSize.Size18,
678 TextWrap = true,
679 TextXAlignment = Enum.TextXAlignment.Left,
680 TextYAlignment = Enum.TextYAlignment.Top,
681 },
682 Obj.Create"TextLabel"
683 {
684 Name = "AbuseLabel",
685 Text = "What did they do?",
686 Font = Enum.Font.Arial,
687 BackgroundTransparency = 1,
688 FontSize = Enum.FontSize.Size18,
689 Position = UDim2.new(0.025,0,0,140),
690 Size = UDim2.new(0.4,0,0,36),
691 TextColor3 = Color3I(255,255,255),
692 TextXAlignment = Enum.TextXAlignment.Left,
693 },
694 Obj.Create"TextLabel"
695 {
696 Name = "ShortDescriptionLabel",
697 Text = "Short Description: (optional)",
698 Font = Enum.Font.Arial,
699 FontSize = Enum.FontSize.Size18,
700 Position = UDim2.new(0.025,0,0,180),
701 Size = UDim2.new(0.95,0,0,36),
702 TextColor3 = Color3I(255,255,255),
703 TextXAlignment = Enum.TextXAlignment.Left,
704 BackgroundTransparency = 1,
705 },
706 Obj.Create"TextLabel"
707 {
708 Name = "ReportingPlayerLabel",
709 Text = "Reporting Player",
710 BackgroundTransparency = 1,
711 Font = Enum.Font.Arial,
712 FontSize = Enum.FontSize.Size18,
713 Position = UDim2.new(0.025,0,0,100),
714 Size = UDim2.new(0.95,0,0,36),
715 TextColor3 = Color3I(255,255,255),
716 TextXAlignment = Enum.TextXAlignment.Left,
717 Parent = AbuseSettingsFrame
718 },
719
720 Parent = ReportAbuseFrame,
721}
722
723local AbusePlayerLabel = Obj.Create"TextLabel"
724{
725 Name = "PlayerLabel",
726 Text = "",
727 BackgroundTransparency = 1,
728 Font = Enum.Font.ArialBold,
729 FontSize = Enum.FontSize.Size18,
730 Position = UDim2.new(0.025,0,0,100),
731 Size = UDim2.new(0.95,0,0,36),
732 TextColor3 = Color3I(255,255,255),
733 TextXAlignment = Enum.TextXAlignment.Right,
734 Parent = AbuseSettingsFrame
735}
736
737local SubmitReportButton = Obj.Create"ImageButton"
738{
739 Name = "SubmitReportBtn",
740 Active = false,
741 BackgroundTransparency = 1,
742 Position = UDim2.new(.5, - 200, 1, - 80),
743 Size = UDim2.new(0,150,0,50),
744 AutoButtonColor = false,
745 Image = 'http://www.roblox.com/asset/?id=96502438', -- 96501119',
746 Parent = AbuseSettingsFrame,
747}
748
749local CancelReportButton = Obj.Create"ImageButton"
750{
751 Name = "CancelBtn",
752 BackgroundTransparency = 1,
753 Position = UDim2.new(0.5, 50, 1, - 80),
754 Size = UDim2.new(0,150,0,50),
755 AutoButtonColor = true,
756 Image = 'http://www.roblox.com/asset/?id=96500683',
757 Parent = AbuseSettingsFrame,
758}
759
760local AbuseDescriptionWrapper = Obj.Create"Frame"
761{
762 Name = "AbuseDescriptionWrapper",
763 Position = UDim2.new(0.025,0,0,220),
764 Size = UDim2.new(0.95,0,1, - 310),
765 BackgroundColor3 = Color3I(0,0,0),
766 BorderSizePixel = 0,
767 Parent = AbuseSettingsFrame,
768}
769
770local AbuseDescriptionBox
771
772local OriginalAbuseDescriptionBox = Obj.Create"TextBox"
773{
774 Name = "TextBox",
775 Text = "",
776 ClearTextOnFocus = false,
777 Font = Enum.Font.Arial,
778 FontSize = Enum.FontSize.Size18,
779 Position = UDim2.new(0,3,0,3),
780 Size = UDim2.new(1, - 6,1, - 6),
781 TextColor3 = Color3I(255,255,255),
782 TextXAlignment = Enum.TextXAlignment.Left,
783 TextYAlignment = Enum.TextYAlignment.Top,
784 TextWrap = true,
785 BackgroundColor3 = Color3I(0,0,0),
786 BorderSizePixel = 0,
787}
788
789local CalmingAbuseBox = Obj.Create'Frame'
790{
791 Name = 'AbuseFeedbackBox',
792 BackgroundTransparency = 1,
793 Position=UDim2.new(0.25, 0, 0.300000012, 0),
794 Size=UDim2.new(0.5, 0, 0.370000005, 0),
795 MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96506233'),
796 Obj.Create'TextLabel'
797 {
798 Name = 'Header',
799 Position=UDim2.new(0,10,.05,0),
800 Size=UDim2.new(1, -30, .15, 0),
801 TextScaled = true,
802 BackgroundTransparency = 1,
803 TextXAlignment = Enum.TextXAlignment.Center,
804 TextYAlignment = Enum.TextYAlignment.Top,
805 Text = 'Thanks for your report!',
806 TextColor3 = Color3.new(1,1,1),
807 FontSize = Enum.FontSize.Size48,
808 Font = 'ArialBold',
809 },
810 Obj.Create'TextLabel'
811 {
812 Name = 'content',
813 Position = UDim2.new(0,10,.20,0),
814 Size = UDim2.new(1, -30, .40, 0),
815 TextScaled = true,
816 BackgroundTransparency = 1,
817 TextColor3 = Color3.new(1,1,1),
818 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',
819 TextWrapped = true,
820 TextYAlignment = Enum.TextYAlignment.Top,
821 FontSize = Enum.FontSize.Size24,
822 Font = 'Arial',
823 },
824 Obj.Create'ImageButton'
825 {
826 Name = "OkButton",
827 BackgroundTransparency = 1,
828 Position = UDim2.new(0.5, -75, 1, -80),
829 Size = UDim2.new(0,150,0,50),
830 AutoButtonColor = true,
831 Image = 'http://www.roblox.com/asset/?id=96507959',
832 }
833}
834local NormalAbuseBox = Obj.Create'Frame'
835{
836 Name = 'AbuseFeedbackBox',
837 BackgroundTransparency = 1,
838 Position = UDim2.new(0.25, 0, 0.300000012, 0),
839 Size = UDim2.new(0.5, 0, 0.370000005, 0),
840 MakeBackgroundGuiObj('http://www.roblox.com/asset/?id=96506233'),
841 Obj.Create'TextLabel'
842 {
843 Name = 'Header',
844 Position = UDim2.new(0,10,.05,0),
845 Size = UDim2.new(1, -30, .15, 0),
846 TextScaled = true,
847 BackgroundTransparency = 1,
848 TextColor3 = Color3.new(1,1,1),
849 TextXAlignment = Enum.TextXAlignment.Center,
850 TextYAlignment = Enum.TextYAlignment.Top,
851 Text = 'Thanks for your report!',
852 FontSize = Enum.FontSize.Size48,
853 Font ='ArialBold'
854 },
855 Obj.Create'TextLabel'
856 {
857 Name = 'content',
858 Position = UDim2.new(0,10,.20,0),
859 Size = UDim2.new(1, -30, .15, 0),
860 TextScaled = true,
861 BackgroundTransparency = 1,
862 TextColor3 = Color3.new(1,1,1),
863 Text = "Our moderators will review the chat logs and determine what happened.",
864 TextWrapped = true,
865 TextYAlignment = Enum.TextYAlignment.Top,
866 FontSize = Enum.FontSize.Size24,
867 Font = 'Arial',
868 },
869 Obj.Create'ImageButton'
870 {
871 Name = "OkButton",
872 BackgroundTransparency = 1,
873 Position = UDim2.new(0.5, -75, 1, -80),
874 Size = UDim2.new(0,150,0,50),
875 AutoButtonColor = true,
876 Image = 'http://www.roblox.com/asset/?id=96507959',
877 },
878}
879
880local BigButton=Instance.new('ImageButton')
881 BigButton.Size=UDim2.new(1,0,1,0)
882 BigButton.BackgroundTransparency=1
883 BigButton.ZIndex=8
884 BigButton.Visible=false
885 --BigButton.Active=false
886 BigButton.Parent=ScreenGui
887
888
889 local debugFrame = Obj.Create"Frame"
890 {
891 Name = 'debugframe',
892 Position = UDim2.new(0, 0, 0, 0),
893 Size = UDim2.new(0, 150, 0, 800),--0.99000001
894 BackgroundTransparency = 1,
895
896 }
897 local debugplayers = Obj.Create"TextLabel"
898 {
899 BackgroundTransparency = .8,
900 Position = UDim2.new(0, 0, .01, 0),
901 Size = UDim2.new(1,0,.5,0),
902 Parent = debugFrame,
903 Font = 'ArialBold',
904 Text = '--',
905 FontSize='Size14',
906 TextWrapped=true,
907 TextColor3 = Color3.new(1,1,1),
908 TextStrokeColor3 = Color3.new(0,0,0),
909 TextStrokeTransparency = 0,
910 TextXAlignment = 'Right',
911 TextYAlignment = 'Center',
912 }
913 local debugOutput = Obj.Create"TextLabel"
914 {
915 BackgroundTransparency = .8,
916 Position = UDim2.new(0, 0, .5, 0),
917 Size = UDim2.new(1,0,.5,0),
918 Parent = debugFrame,
919 Font = 'ArialBold',
920 Text = '--',
921 FontSize='Size14',
922 TextWrapped=true,
923 TextColor3 = Color3.new(1,1,1),
924 TextStrokeColor3 = Color3.new(0,0,0),
925 TextStrokeTransparency = 0,
926 TextXAlignment = 'Right',
927 TextYAlignment = 'Center',
928 }
929
930
931--[[
932 simple function to toggle the display of debug output
933--]]
934local DebugPrintEnabled=true
935function debugprint(str)
936 --print(str)
937 if DebugPrintEnabled then
938 debugOutput.Text=str
939 end
940end
941
942
943 -------------------------
944 -- Script objects
945 -------------------------
946local RbxGui = assert(LoadLibrary('RbxGui'))
947
948 -- number of entries to show if you click minimize
949local DefaultEntriesOnScreen = 8
950
951
952
953
954
955for _,i in pairs(Images) do
956 Game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id="..i)
957end
958
959 -- ordered array of 'score data', each entry has:
960 -- Name(String)
961 -- Priority(number)
962 -- IsPrimary (bool, should it be shown in upper right)
963 -- MaxLength (integer, of the length of the longest element for this column)
964local ScoreNames = {}
965 -- prevents flipping in playerlist panels
966local AddId = 0
967 -- intermediate table form of all player entries in format of:
968 -- Frame
969 -- Player
970 -- Score
971 -- ID
972 -- MyTeam (team ENRTY(not actual team) I am currently on)
973local PlayerFrames = {}
974 -- intermediate ordered frame array, composed of Entrys of
975 -- Frame
976 -- MyTeam (my team object)
977 -- MyPlayers ( an ordered array of all player frames in team )
978 -- AutoHide (bool saying whether it should be hidden)
979 -- IsHidden (bool)
980 -- ID (int to prevent flipping out of leaderboard, fun times)
981local TeamFrames = {}
982 -- one special entry from teamFrames, for unaffiliated players, only shown if players non - empty
983local NeutralTeam = nil
984
985 -- final 'to be displayed' list of frames
986local MiddleFrames = {}
987local MiddleFrameBackgrounds = {}
988local MiddleFrameHeight = .03
989 -- time of last click
990local LastClick = 0
991local ButtonCooldown = .25
992
993local OnIos = false
994pcall(function() OnIos = Game:GetService('UserInputService').TouchEnabled end)
995
996
997 -- you get 200 of x screen space per stat added, start width 16%
998local BaseScreenXSize = 150
999local SpacingPerStat = 10 --spacing between stats
1000
1001
1002local MaximizedBounds = UDim2.new(.5,0,1,0)
1003local MaximizedPosition = UDim2.new(.25,0,.1,0)
1004local NormalBounds = UDim2.new(0,BaseScreenXSize, 0, 800)
1005local NormalPosition = UDim2.new(1 , - BaseScreenXSize, 0.005, 0)
1006
1007local MinimizedBounds = UDim2.new(0, BaseScreenXSize, 0.99000001, 0)
1008
1009--free space to give last stat on the right
1010local RightEdgeSpace = -.04
1011
1012 -- where the scroll par currently is positioned
1013local ScrollPosition = 0.75999999
1014local IsDragging = false -- am I dragging the player list
1015
1016local DefaultBottomClipPos = BottomClipFrame.Position.Y.Scale
1017
1018local LastSelectedPlayerEntry = nil
1019local SelectedPlayerEntry = nil
1020local SelectedPlayer = nil
1021
1022 -- locks(semaphores) for stopping race conditions
1023local AddingFrameLock = false
1024local ChangingOrderLock = false
1025local AddingStatLock = false
1026local BaseUpdateLock = false
1027local WaitForClickLock = false
1028local InPopupWaitForClick=false
1029local PlayerChangedLock = false
1030local NeutralTeamLock = false
1031
1032local ScrollWheelConnections = {}
1033
1034
1035local DefaultListSize = 15
1036if not OnIos then DefaultListSize = 24 end
1037local DidMinimizeDrag = false
1038
1039--local PlaceCreatorId=game.CreatorId
1040
1041 -- report abuse objects
1042local AbuseName
1043local Abuses = {
1044 "Bad Words or Threats",
1045 "Bad Username",
1046 "Talking about Dating",
1047 "Account Trading or Sharing",
1048 "Asking Personal Questions",
1049 "Rude or Mean Behavior",
1050 "False Reporting Me"
1051}
1052local UpdateAbuseFunction
1053local AbuseDropDown, UpdateAbuseSelection
1054
1055local PrivilegeLevel =
1056{
1057 Owner = 255,
1058 Admin = 240,
1059 Member = 128,
1060 Visitor = 10,
1061 Banned = 0,
1062}
1063
1064
1065local IsPersonalServer = not not game.Workspace:FindFirstChild("PSVariable")
1066
1067game.Workspace.ChildAdded:connect(function(nchild)
1068 if nchild.Name=='PSVariable' and nchild:IsA('BoolValue') then
1069 IsPersonalServer=true
1070 end
1071end)
1072 -------------------------------
1073 -- Static Functions
1074 -------------------------------
1075function GetTotalEntries()
1076 return math.min(#MiddleFrameBackgrounds,DefaultEntriesOnScreen)
1077end
1078
1079function GetEntryListLength()
1080 local numEnts=#PlayerFrames+#TeamFrames
1081 if NeutralTeam then
1082 numEnts=numEnts+1
1083 end
1084 return numEnts
1085end
1086
1087function AreAllEntriesOnScreen()
1088 return #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale <= 1 + DefaultBottomClipPos
1089end
1090
1091function GetLengthOfVisbleScroll()
1092 return 1 + DefaultBottomClipPos
1093end
1094
1095function GetMaxScroll()
1096 return DefaultBottomClipPos * - 1
1097end
1098 -- can be optimized by caching when this varible changes
1099function GetMinScroll()
1100 if AreAllEntriesOnScreen() then
1101 return GetMaxScroll()
1102 else
1103 return (GetMaxScroll() - (#MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale)) + (1 + DefaultBottomClipPos)
1104 end
1105end
1106
1107function AbsoluteToPercent(x,y)
1108 return Vector2.new(x,y)/ScreenGui.AbsoluteSize
1109end
1110--[[
1111 tweens property of element from starta to enda over length of time
1112 Warning: should be put in a Spawn call
1113 @Args:
1114 element textobject to tween transparency on
1115 propName
1116 starta alpha to start tweening
1117 enda alpha to end tweening on
1118 length how many seconds to spend tweening
1119--]]
1120function TweenProperty(obj, propName, inita, enda, length)
1121 local startTime = tick()
1122 while tick()-startTime<length do
1123 obj[propName] = ((enda-inita)*((tick()-startTime)/length))+inita
1124 wait(1/30)
1125 end
1126 obj[propName] = enda
1127end
1128--[[
1129 UGLY UGLY HACK FUNCTION
1130 replace with some sort of global input catching A.S.A. FREAKING P.
1131 creates a fullsize gui element to catch next mouse up event(completeing a click)
1132 @Args:
1133 frameParent Object to parent fullscreen gui to
1134 polledFunction function to call on mouse moved events in this gui
1135 exitFunction function to call when click event is fired
1136--]]
1137
1138function WaitForClick(frameParent,polledFunction,exitFunction)
1139
1140 if WaitForClickLock then return end
1141 WaitForClickLock=true
1142 local upHappened=false
1143 local connection, connection2
1144 connection=BigButton.MouseButton1Up:connect(function(nx,ny)
1145 exitFunction(nx,ny)
1146 BigButton.Visible=false
1147 connection:disconnect()
1148 if connection2 then
1149 connection2:disconnect()
1150 end
1151 --debugprint('mouse up!')
1152 end)
1153 connection2=BigButton.MouseMoved:connect( function(nx,ny)
1154 polledFunction(nx,ny)
1155
1156 end)
1157
1158 --debugprint('waiting for click!')
1159 BigButton.Visible=true
1160 BigButton.Active=true
1161 BigButton.Parent=frameParent
1162 frameParent.AncestryChanged:connect(function(child,nparent)
1163 if child == frameParent and nparent ==nil then
1164 exitFunction(nx,ny)
1165 BigButton.Visible=false
1166 connection:disconnect()
1167 connection2:disconnect()
1168 debugprint("forced out of wait for click")
1169 end
1170 end)
1171 WaitForClickLock=false
1172end
1173
1174
1175
1176---------------------------
1177--Personal Server Handling
1178---------------------------
1179--[[
1180 returns privlage level based on integer rank
1181 Note: these privilege levels seem completely arbitrary, but no documentation exists
1182 this is all from the old player list, really weird
1183 @Args:
1184 rank Integer rank value for player
1185 @Return Normalized integer value for rank?
1186--]]
1187function GetPrivilegeType(rank)
1188 if rank <= PrivilegeLevel['Banned'] then
1189 return PrivilegeLevel['Banned']
1190 elseif rank <= PrivilegeLevel['Visitor'] then
1191 return PrivilegeLevel['Visitor']
1192 elseif rank <= PrivilegeLevel['Member'] then
1193 return PrivilegeLevel['Member']
1194 elseif rank <= PrivilegeLevel['Admin'] then
1195 return PrivilegeLevel['Admin']
1196 else
1197 return PrivilegeLevel['Owner']
1198 end
1199end
1200
1201--[[
1202 gives a player a new privilage rank
1203 Note: Very odd that I have to use loops with this instead of directly setting the rank
1204 but no documentation for personal server service exists
1205 @Args:
1206 player player to change rank of
1207 nrank new integer rank to give player
1208--]]
1209function SetPrivilegeRank(player,nrank)
1210 while player.PersonalServerRank<nrank do
1211 game:GetService("PersonalServerService"):Promote(player)
1212 end
1213 while player.PersonalServerRank>nrank do
1214 game:GetService("PersonalServerService"):Demote(player)
1215 end
1216end
1217--[[
1218 called when player selects new privilege level from popup menu
1219 @Args:
1220 player player to set privileges on
1221 nlevel new privilege level for this player
1222--]]
1223function OnPrivilegeLevelSelect(player,nlevel,BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1224 debugprint('setting privilege level')
1225 SetPrivilegeRank(player,nlevel)
1226 HighlightMyRank(player,BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1227end
1228
1229--[[
1230 Highlights current rank of this player in the popup menu
1231 @Args:
1232 player Player to check for rank on
1233--]]
1234function HighlightMyRank(player,BanPlayerButton,VisitorButton,MemberButton,AdminButton)
1235 BanPlayerButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid']
1236 VisitorButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupMid']
1237 MemberButton.Image= 'http://www.roblox.com/asset/?id='..Images['LightPopupMid']
1238 AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkPopupBottom']
1239
1240 local rank=player.PersonalServerRank
1241 if rank <= PrivilegeLevel['Banned'] then
1242 BanPlayerButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid']
1243 elseif rank <= PrivilegeLevel['Visitor'] then
1244 VisitorButton.Image='http://www.roblox.com/asset/?id='..Images['DarkBluePopupMid']
1245 elseif rank <= PrivilegeLevel['Member'] then
1246 MemberButton.Image='http://www.roblox.com/asset/?id='..Images['LightBluePopupMid']
1247 elseif rank <= PrivilegeLevel['Admin'] then
1248 AdminButton.Image= 'http://www.roblox.com/asset/?id='..Images['DarkBluePopupBottom']
1249 end
1250end
1251
1252 --------------------------
1253 -- Report abuse handling
1254 --------------------------
1255--[[
1256 does final reporting of abuse on selected player, calls closeAbuseDialog
1257--]]
1258function OnSubmitAbuse()
1259 if SubmitReportButton.Active then
1260 if AbuseName and SelectedPlayer then
1261 AbuseSettingsFrame.Visible = false
1262 game.Players:ReportAbuse(SelectedPlayer, AbuseName, AbuseDescriptionBox.Text)
1263 if AbuseName == "Rude or Mean Behavior" or AbuseName == "False Reporting Me" then
1264 CalmingAbuseBox.Parent = ReportAbuseShield
1265 else
1266 debugprint('opening abuse box')
1267 NormalAbuseBox.Parent = ReportAbuseShield
1268 end
1269 else
1270 CloseAbuseDialog()
1271 end
1272 end
1273end
1274
1275--[[
1276 opens the abuse dialog, initialises text to display selectedplayer
1277--]]
1278function OpenAbuseDialog()
1279 debugprint('adding report dialog')
1280 AbusePlayerLabel.Text = SelectedPlayer.Name
1281 --AbuseDescriptionBox.Text = ""
1282 PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
1283 AbuseDescriptionBox=OriginalAbuseDescriptionBox:Clone()
1284 AbuseDescriptionBox.Parent = AbuseDescriptionWrapper
1285 ReportAbuseShield.Parent = ScreenGui
1286 ClosePopUpPanel()
1287end
1288--[[
1289 resets and closes abuse dialog
1290--]]
1291function CloseAbuseDialog()
1292 AbuseName = nil
1293 SubmitReportButton.Active = false
1294 SubmitReportButton.Image = 'http://www.roblox.com/asset/?id=96502438' -- 96501119',
1295 AbuseDescriptionBox:Destroy()
1296 CalmingAbuseBox.Parent = nil
1297 NormalAbuseBox.Parent = nil
1298 ReportAbuseShield.Parent = nil
1299 AbuseSettingsFrame.Visible = true
1300end
1301
1302--[[
1303 creates dropdownbox, registers all listeners for abuse dialog
1304--]]
1305function InitReportAbuse()
1306
1307 UpdateAbuseFunction = function(abuseText)
1308 AbuseName = abuseText
1309 if AbuseName and SelectedPlayer then
1310 SubmitReportButton.Active = true
1311 SubmitReportButton.Image = 'http://www.roblox.com/asset/?id=96501119'
1312 end
1313 end
1314
1315 AbuseDropDown, UpdateAbuseSelection = RbxGui.CreateDropDownMenu(Abuses, UpdateAbuseFunction, true)
1316 AbuseDropDown.Name = "AbuseComboBox"
1317 AbuseDropDown.Position = UDim2.new(0.425, 0, 0, 142)
1318 AbuseDropDown.Size = UDim2.new(0.55,0,0,32)
1319 AbuseDropDown.Parent = AbuseSettingsFrame
1320
1321
1322 CancelReportButton.MouseButton1Click:connect(CloseAbuseDialog)
1323 SubmitReportButton.MouseButton1Click:connect(OnSubmitAbuse)
1324
1325 CalmingAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog)
1326 NormalAbuseBox:FindFirstChild('OkButton').MouseButton1Down:connect(CloseAbuseDialog)
1327end
1328
1329-------------------------------------
1330-- Friend/unfriending
1331-------------------------------------
1332--[[
1333 gets enum val of friend status, uses pcall for some reason?(from old playerlist)
1334 @Args:
1335 player player object to check if friends with
1336 @Return: enum of friend status
1337--]]
1338local function GetFriendStatus(player)
1339 if player == game.Players.LocalPlayer then
1340 return Enum.FriendStatus.NotFriend
1341 else
1342 local success, result = pcall(function() return game.Players.LocalPlayer:GetFriendStatus(player) end)
1343 if success then
1344 return result
1345 else
1346 return Enum.FriendStatus.NotFriend
1347 end
1348 end
1349end
1350
1351--[[
1352 when friend button is clicked, tries to take appropriate action,
1353 based on current friend status with SelectedPlayer
1354--]]
1355function OnFriendButtonSelect()
1356
1357 local friendStatus=GetFriendStatus(SelectedPlayer)
1358 if friendStatus==Enum.FriendStatus.Friend then
1359 LocalPlayer:RevokeFriendship(SelectedPlayer)
1360 elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then
1361 LocalPlayer:RequestFriendship(SelectedPlayer)
1362 elseif friendStatus==Enum.FriendStatus.FriendRequestSent then
1363 LocalPlayer:RevokeFriendship(SelectedPlayer)
1364 elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then
1365 LocalPlayer:RequestFriendship(SelectedPlayer)
1366 end
1367 --PersonalServerPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Quad", .5,true)
1368 ClosePopUpPanel()
1369 --PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
1370end
1371
1372function OnFriendRefuseButtonSelect()
1373
1374
1375 LocalPlayer:RevokeFriendship(SelectedPlayer)
1376 ClosePopUpPanel()
1377 PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
1378end
1379------------------------------------
1380-- Player Entry Handling
1381------------------------------------
1382--[[
1383 used by lua's table.sort to sort player entries
1384--]]
1385function PlayerSortFunction(a,b)
1386 -- prevents flipping out leaderboard
1387 if a['Score'] == b['Score'] then
1388 return a['Player'].Name:upper() < b['Player'].Name:upper()
1389 end
1390 if not a['Score'] then return false end
1391 if not b['Score'] then return true end
1392 return a['Score'] < b['Score']
1393end
1394
1395 ---------------------------------
1396 -- Stat Handling
1397 ---------------------------------
1398 -- removes and closes all leaderboard stuffs
1399function BlowThisPopsicleStand()
1400 --ScreenGui:Destroy()
1401 --script:Destroy()
1402 --time to make the fanboys rage...
1403 Tabify()
1404end
1405--[[
1406 used by lua's table.sort to prioritize score entries
1407--]]
1408function StatSort(a,b)
1409 -- primary stats should be shown before all others
1410 if a.IsPrimary ~= b.IsPrimary then
1411 return a.IsPrimary
1412 end
1413 -- if priorities are equal, then return the first added one
1414 if a.Priority == b.Priority then
1415 return a.AddId < b.AddId
1416 end
1417 return a.Priority < b.Priority
1418end
1419--[[
1420 doing WAAY too much here, for optimization update only your team
1421 @Args:
1422 playerEntry Entry of player who had a stat change
1423 property Name of stat changed
1424--]]
1425function StatChanged(playerEntry,property)
1426
1427 -- if(playerEntry['MyTeam']) then
1428 -- UpdateSingleTeam(playerEntry['MyTeam'])
1429 -- else
1430 BaseUpdate()
1431 -- end
1432end
1433--[[
1434 Called when stat is added
1435 if playerEntry is localplayer, will add to score names and re-sort the stats, and resize the width of the leaderboard
1436 for all players, will add a listener for if this stat changes
1437 if stat is a string value, crashes the leaderboard
1438 Note:change crash to a 'tabify' leaderboard later
1439 @Args:
1440 nchild new child value to leaderstats
1441 playerEntry entry this stat was added to
1442--]]
1443function StatAdded(nchild,playerEntry)
1444 -- dont re - add a leaderstat I alreday have
1445 while AddingStatLock do debugprint('in stat added function lock') wait(1/30) end
1446 AddingStatLock = true
1447 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
1448 BlowThisPopsicleStand()
1449 else
1450 local haveScore = false
1451 for _,i in pairs(ScoreNames) do
1452 if i['Name']==nchild.Name then haveScore=true end
1453 end
1454 if not haveScore then
1455 local nstat = {}
1456 nstat['Name'] = nchild.Name
1457 nstat['Priority'] = 0
1458 if(nchild:FindFirstChild('Priority')) then
1459 nstat['Priority'] = nchild.Priority
1460 end
1461 nstat['IsPrimary'] = false
1462 if(nchild:FindFirstChild('IsPrimary')) then
1463 nstat['IsPrimary'] = true
1464 end
1465 nstat.AddId = AddId
1466 AddId = AddId + 1
1467 table.insert(ScoreNames,nstat)
1468 table.sort(ScoreNames,StatSort)
1469 if not StatTitles:FindFirstChild(nstat['Name']) then
1470 CreateStatTitle(nstat['Name'])
1471 end
1472 UpdateMaximize()
1473
1474 end
1475 end
1476 AddingStatLock = false
1477 StatChanged(playerEntry)
1478 nchild.Changed:connect(function(property) StatChanged(playerEntry,property) end)
1479
1480
1481end
1482--returns whether any of the existing players has this stat
1483function DoesStatExist(statName, exception)
1484 for _,playerf in pairs(PlayerFrames) do
1485 if playerf['Player'] ~= exception and playerf['Player']:FindFirstChild('leaderstats') and playerf['Player'].leaderstats:FindFirstChild(statName) then
1486 --print('player:' .. playerf['Player'].Name ..' has stat')
1487 return true
1488 end
1489 end
1490 return false
1491end
1492
1493
1494
1495--[[
1496 Called when stat is removed from player
1497 for all players, destroys the stat frame associated with this value,
1498 then calls statchanged(to resize frame)
1499 if playerEntry==localplayer, will remove from scorenames
1500 @Args:
1501 nchild ___value to be removed
1502 playerEntry entry of player value is being removed from
1503--]]
1504function StatRemoved(nchild,playerEntry)
1505 while AddingStatLock do debugprint('In Adding Stat Lock1') wait(1/30) end
1506 AddingStatLock = true
1507 if playerEntry['Frame']:FindFirstChild(nchild.Name) then
1508 debugprint('Destroyed frame!')
1509 playerEntry['Frame'][nchild.Name].Parent = nil
1510 end
1511 if not DoesStatExist(nchild.Name, playerEntry['Player']) then
1512 for i,val in ipairs(ScoreNames) do
1513 if val['Name'] == nchild.Name then
1514 table.remove(ScoreNames,i)
1515 if StatTitles:FindFirstChild(nchild.Name) then
1516 StatTitles[nchild.Name]:Destroy()
1517 end
1518 for _,teamf in pairs(TeamFrames) do
1519 if teamf['Frame']:FindFirstChild(nchild.Name) then
1520 teamf['Frame'][nchild.Name]:Destroy()
1521 end
1522 end
1523 end
1524 end
1525 end
1526 AddingStatLock = false
1527 StatChanged(playerEntry)
1528end
1529--[[
1530 clears all stats from a given playerEntry
1531 used when leaderstats are removed, or when new leaderstats are added(for weird edge case)+
1532--]]
1533function RemoveAllStats(playerEntry)
1534 for i,val in ipairs(ScoreNames) do
1535 StatRemoved(val,playerEntry)
1536 end
1537
1538end
1539
1540
1541function GetScoreValue(score)
1542 if score:IsA('DoubleConstrainedValue') or score:IsA('IntConstrainedValue') then
1543 return score.ConstrainedValue
1544 elseif score:IsA('BoolValue') then
1545 if score.Value then return 1 else return 0 end
1546 else
1547 return score.Value
1548 end
1549end
1550--[[
1551
1552--]]
1553function MakeScoreEntry(entry,scoreval,panel)
1554 if not panel:FindFirstChild('PlayerScore') then return end
1555 local nscoretxt = panel:FindFirstChild('PlayerScore'):Clone()
1556 local thisScore = nil
1557 --here lies the resting place of a once great and terrible bug
1558 --may its treachery never be forgoten, lest its survivors fall for it again
1559 --RIP the leaderstat bug, oct 2012-nov 2012
1560 wait()
1561 if entry['Player']:FindFirstChild('leaderstats') and entry['Player'].leaderstats:FindFirstChild(scoreval['Name']) then
1562 thisScore = entry['Player']:FindFirstChild('leaderstats'):FindFirstChild(scoreval['Name'])
1563 else
1564 return
1565 end
1566
1567 if not entry['Player'].Parent then return end
1568
1569 nscoretxt.Name = scoreval['Name']
1570 nscoretxt.Text = tostring(GetScoreValue(thisScore))
1571 if scoreval['Name'] == ScoreNames[1]['Name'] then
1572 debugprint('changing score')
1573 entry['Score'] = GetScoreValue(thisScore)
1574 if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end
1575 end
1576
1577 thisScore.Changed:connect(function()
1578 if not thisScore.Parent then return end
1579 if scoreval['Name'] == ScoreNames[1]['Name'] then
1580
1581 entry['Score'] = GetScoreValue(thisScore)
1582 if entry['Player'] == LocalPlayer then HeaderScore.Text = tostring(GetScoreValue(thisScore)) end
1583 end
1584 nscoretxt.Text = tostring(GetScoreValue(thisScore))
1585 BaseUpdate()
1586 end)
1587 return nscoretxt
1588
1589end
1590
1591function CreateStatTitle(statName)
1592
1593 local ntitle = MiddleTemplate:FindFirstChild('PlayerScore'):Clone()
1594 ntitle.Name = statName
1595 ntitle.Text = statName
1596 -- ntitle
1597 if IsMaximized.Value then
1598 ntitle.TextTransparency = 0
1599 else
1600 ntitle.TextTransparency = 1
1601 end
1602 ntitle.Parent = StatTitles
1603end
1604
1605function RecreateScoreColumns(ptable)
1606 while AddingStatLock do debugprint ('In Adding Stat Lock2') wait(1/30) end
1607 AddingStatLock = true
1608 local Xoffset=5--15 --current offset from Right
1609 local maxXOffset=Xoffset
1610 local MaxSizeColumn=0 --max size for this column
1611
1612 -- foreach known leaderstat
1613 for j = #ScoreNames, 1,-1 do
1614 local scoreval = ScoreNames[j]
1615
1616 MaxSizeColumn=0
1617 -- for each entry in this player table
1618 for i,entry in ipairs(ptable) do
1619 local panel = entry['Frame']
1620 local tplayer = entry['Player']
1621 -- if this panel does not have an element named after this stat
1622 if not panel:FindFirstChild(scoreval['Name']) then
1623 -- make an entry for this object
1624 local nentry = MakeScoreEntry(entry,scoreval,panel)
1625 if nentry then
1626 debugprint('adding '..nentry.Name..' to '..entry['Player'].Name )
1627 nentry.Parent = panel
1628 -- add score to team
1629 if entry['MyTeam'] and entry['MyTeam'] ~= NeutralTeam and not entry['MyTeam']['Frame']:FindFirstChild(scoreval['Name']) then
1630 local ntitle = nentry:Clone()
1631 --ntitle.TextXAlignment = 'Right'
1632 ntitle.Parent = entry['MyTeam']['Frame']
1633 end
1634
1635 end
1636 end
1637 scoreval['XOffset']=Xoffset
1638
1639 if panel:FindFirstChild(scoreval['Name']) then
1640 MaxSizeColumn=math.max(MaxSizeColumn,panel[scoreval['Name']].TextBounds.X)
1641 end
1642 end
1643
1644 if AreNamesExpanded.Value then
1645 MaxSizeColumn=math.max(MaxSizeColumn,StatTitles[scoreval['Name'] ].TextBounds.X)
1646 StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(RightEdgeSpace,-Xoffset,0,0),'Out','Linear',BASE_TWEEN,true)
1647 else
1648 StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new((.4+((.6/#ScoreNames)*(j-1)))-1,0,0,0),'Out','Linear',BASE_TWEEN,true)
1649 end
1650 scoreval['ColumnSize']=MaxSizeColumn
1651 Xoffset= Xoffset+SpacingPerStat+MaxSizeColumn
1652 maxXOffset=math.max(Xoffset,maxXOffset)
1653 end
1654 NormalBounds = UDim2.new(0, BaseScreenXSize+maxXOffset-SpacingPerStat,0,800)
1655 NormalPosition = UDim2.new(1 , -NormalBounds.X.Offset, NormalPosition.Y.Scale, 0)
1656 UpdateHeaderNameSize()
1657 UpdateMaximize()
1658
1659 AddingStatLock = false
1660end
1661 ---------------------------
1662 -- Minimizing and maximizing
1663 ---------------------------
1664
1665function ToggleMinimize()
1666 IsMinimized.Value = not IsMinimized.Value
1667 UpdateStatNames()
1668end
1669
1670function ToggleMaximize()
1671 IsMaximized.Value = not IsMaximized.Value
1672 RecreateScoreColumns(PlayerFrames) --done to re-position stat names NOTE: optimize-able
1673end
1674
1675function Tabify()
1676 IsTabified.Value= true
1677 IsMaximized.Value=false
1678 IsMinimized.Value=true
1679 UpdateMinimize()
1680 IsTabified.Value= true
1681 ScreenGui:TweenPosition(UDim2.new(NormalBounds.X.Scale, NormalBounds.X.Offset-10, 0,0),'Out','Linear',BASE_TWEEN*1.2,true)
1682end
1683
1684function UnTabify()
1685 if IsTabified.Value then
1686 IsTabified.Value= false
1687 ScreenGui:TweenPosition(UDim2.new(0, 0, 0,0),'Out','Linear',BASE_TWEEN*1.2,true)
1688 end
1689end
1690
1691--[[
1692 Does more than it looks like
1693 monitors positions of the clipping frames and bottom frames
1694 called from EVERYWHERE, too much probably
1695--]]
1696function UpdateMinimize()
1697
1698 if IsMinimized.Value then
1699 if IsMaximized.Value then
1700 ToggleMaximize()
1701 end
1702 if not IsTabified.Value then
1703 MainFrame.Size = UDim2.new(0.010, HeaderName.TextBounds.X, NormalBounds.Y.Scale,NormalBounds.Y.Offset)
1704 MainFrame.Position = UDim2.new(.990, -HeaderName.TextBounds.X, NormalPosition.Y.Scale,0)
1705 else
1706 MainFrame.Size = NormalBounds
1707 MainFrame.Position = NormalPosition
1708 end
1709 --(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale)
1710 BottomClipFrame.Position = UDim2.new(0,0,-1,0)
1711 BottomFrame.Position = UDim2.new(0,0,0,0)
1712 FocusFrame.Size=UDim2.new(1,0,HeaderFrameHeight,0)
1713 ExtendTab.Image = 'http://www.roblox.com/asset/?id=94692731'
1714 else
1715 if not IsMaximized.Value then
1716 MainFrame.Size = NormalBounds
1717 MainFrame.Position = NormalPosition
1718 end
1719 --do limiting
1720 DefaultBottomClipPos = math.min(math.max(DefaultBottomClipPos,-1),-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale))
1721 UpdateScrollPosition()
1722
1723 BottomClipFrame.Position=UDim2.new(0,0,DefaultBottomClipPos,0)
1724 local bottomPositon = (DefaultBottomClipPos+BottomClipFrame.Size.Y.Scale)
1725 BottomFrame.Position=UDim2.new(0,0,bottomPositon,0)
1726 FocusFrame.Size=UDim2.new(1,0,bottomPositon + HeaderFrameHeight,0)
1727 ExtendTab.Image = 'http://www.roblox.com/asset/?id=94825585'
1728 end
1729end
1730
1731--[[
1732 Manages the position/size of the mainFrame, swaps out different resolution images for the frame
1733 fades in and out the stat names, moves position of headername and header score
1734--]]
1735function UpdateMaximize()
1736 if IsMaximized.Value then
1737 for j = 1, #ScoreNames,1 do
1738 local scoreval = ScoreNames[j]
1739 StatTitles[scoreval['Name'] ]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1))-1,0,0,0),'Out','Linear',BASE_TWEEN,true)
1740 end
1741
1742 if IsMinimized.Value then
1743 ToggleMinimize()
1744 else
1745 UpdateMinimize()
1746 end
1747
1748
1749 MainFrame:TweenSizeAndPosition(MaximizedBounds,MaximizedPosition,'Out','Linear',BASE_TWEEN*1.2,true)
1750 HeaderScore:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1751 HeaderName:TweenPosition(UDim2.new( - .1, - HeaderScore.TextBounds.x,HeaderName.Position.Y.Scale,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1752 HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeHeader']
1753 BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeBottom']
1754 for index, i in ipairs(MiddleFrameBackgrounds) do
1755 if (index%2) ~= 1 then
1756 i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeDark']
1757 else
1758 i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeLight']
1759 end
1760 end
1761 for index, i in ipairs(MiddleFrames) do
1762 if i:FindFirstChild('ClickListener') then
1763 i.ClickListener.Size = UDim2.new(.974,0,i.ClickListener.Size.Y.Scale,0)
1764 end
1765 for j=1, #ScoreNames,1 do
1766 local scoreval = ScoreNames[j]
1767 if i:FindFirstChild(scoreval['Name']) then
1768 i[scoreval['Name']]:TweenPosition(UDim2.new(.4+((.6/#ScoreNames)*(j-1))-1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
1769 end
1770 end
1771 end
1772 for i,entry in ipairs(PlayerFrames) do
1773 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1774 end
1775
1776 for i,entry in ipairs(TeamFrames) do
1777 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(.38,0,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1778 end
1779
1780 else
1781 if not IsMinimized.Value then
1782 MainFrame:TweenSizeAndPosition(NormalBounds,NormalPosition,'Out','Linear',BASE_TWEEN*1.2,true)
1783 end
1784 HeaderScore:TweenPosition(UDim2.new(0,0,.4,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1785 HeaderName:TweenPosition(UDim2.new(0,0,HeaderName.Position.Y.Scale,0), "Out", "Linear", BASE_TWEEN*1.2,true)
1786 HeaderFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalHeader']
1787 BottomFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['NormalBottom']
1788 for index, i in ipairs(MiddleFrameBackgrounds) do
1789 if index%2 ~= 1 then
1790 i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midDark']
1791 else
1792 i.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midLight']
1793 end
1794 end
1795 for index, i in ipairs(MiddleFrames) do
1796 if i:FindFirstChild('ClickListener') then
1797 i.ClickListener.Size = UDim2.new(.96,0,i.ClickListener.Size.Y.Scale,0)
1798 for j=1, #ScoreNames,1 do
1799 local scoreval = ScoreNames[j]
1800 if i:FindFirstChild(scoreval['Name']) and scoreval['XOffset'] then
1801 --print('updateing stat position: ' .. scoreval['Name'])
1802 i[scoreval['Name']]:TweenPosition(UDim2.new(RightEdgeSpace,-scoreval['XOffset'],0,0), "Out", "Linear", BASE_TWEEN,true)
1803 end
1804 end
1805 end
1806 end
1807
1808 for i,entry in ipairs(TeamFrames) do
1809 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1810
1811 end
1812 for i,entry in ipairs(PlayerFrames) do
1813 WaitForChild(entry['Frame'],'TitleFrame').Size=UDim2.new(0,BaseScreenXSize*.9,entry['Frame'].TitleFrame.Size.Y.Scale,0)
1814 end
1815 end
1816end
1817
1818function UpdateStatNames()
1819 if not AreNamesExpanded.Value or IsMinimized.Value then
1820 CloseNames()
1821 else
1822 ExpandNames()
1823 end
1824end
1825
1826function ExpandNames()
1827 if #ScoreNames ~= 0 then
1828 for _,i in pairs(StatTitles:GetChildren()) do
1829 Spawn(function()TweenProperty(i,'TextTransparency',i.TextTransparency,0,BASE_TWEEN) end)
1830 end
1831 HeaderFrameHeight=.09
1832 --as of writing, this and 'CloseNames' are the only places headerframe is resized
1833 HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0),
1834 HeaderFrame.Position,'Out','Linear',BASE_TWEEN*1.2,true)
1835 TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Linear',BASE_TWEEN*1.2,true)
1836 BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Linear', BASE_TWEEN*1.2,true)
1837
1838 end
1839
1840end
1841
1842function CloseNames()
1843 if #ScoreNames ~= 0 then
1844 HeaderFrameHeight=.07
1845 if not (IsMaximized.Value) then
1846 for _,i in pairs(StatTitles:GetChildren()) do
1847 Spawn(function()TweenProperty(i,'TextTransparency',i.TextTransparency,1,BASE_TWEEN) end)
1848 end
1849 end
1850 BottomShiftFrame:TweenPosition(UDim2.new(0,0,HeaderFrameHeight,0), "Out", 'Linear', BASE_TWEEN*1.2,true)
1851 HeaderFrame:TweenSizeAndPosition(UDim2.new(HeaderFrame.Size.X.Scale, HeaderFrame.Size.X.Offset, HeaderFrameHeight,0),
1852 HeaderFrame.Position,'Out','Linear',BASE_TWEEN*1.2,true)
1853 TopClipFrame:TweenPosition(UDim2.new(TopClipFrame.Position.X.Scale,0,HeaderFrameHeight,0),'Out','Linear',BASE_TWEEN*1.2,true)
1854 end
1855end
1856
1857function OnScrollWheelMove(direction)
1858 if not (IsTabified.Value or IsMinimized.Value or InPopupWaitForClick) then
1859 local StartFrame = ListFrame.Position
1860 local newFrameY = math.max(math.min(StartFrame.Y.Scale + (direction),GetMaxScroll()),GetMinScroll())
1861
1862 ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset)
1863 UpdateScrollPosition()
1864 end
1865end
1866
1867function AttachScrollWheel()
1868 if ScrollWheelConnections then return end
1869 ScrollWheelConnections = {}
1870 table.insert(ScrollWheelConnections,Mouse.WheelForward:connect(function()
1871 OnScrollWheelMove(.05)
1872 end))
1873 table.insert(ScrollWheelConnections,Mouse.WheelBackward:connect(function()
1874 OnScrollWheelMove(-.05)
1875 end))
1876end
1877
1878function DetachScrollWheel()
1879 if ScrollWheelConnections then
1880 for _,i in pairs(ScrollWheelConnections) do
1881 i:disconnect()
1882 end
1883 end
1884 ScrollWheelConnections=nil
1885end
1886
1887FocusFrame.MouseEnter:connect(function()
1888 if not (IsMinimized.Value or IsTabified.Value) then
1889 AttachScrollWheel()
1890 end
1891end)
1892FocusFrame.MouseLeave:connect(function()
1893 --if not (IsMaximized.Value or IsMinimized.Value) then
1894 DetachScrollWheel()
1895 --end
1896end)
1897
1898 ------------------------
1899 -- Scroll Bar functions
1900 ------------------------
1901--[[
1902 updates whether the scroll bar should be showing, if it is showing, updates
1903 the size of it
1904--]]
1905function UpdateScrollBarVisibility()
1906 if AreAllEntriesOnScreen() then
1907 ScrollBar.BackgroundTransparency = 1
1908 else
1909 ScrollBar.BackgroundTransparency = 0
1910 UpdateScrollBarSize()
1911 end
1912end
1913--[[
1914 updates size of scrollbar depending on how many entries exist
1915--]]
1916function UpdateScrollBarSize()
1917 local entryListSize = #MiddleFrameBackgrounds * MiddleTemplate.Size.Y.Scale
1918 local shownAreaSize = ((BottomClipFrame.Position.Y.Scale) + 1)
1919 ScrollBar.Size = UDim2.new(1,0,shownAreaSize/entryListSize,0)
1920
1921end
1922--[[
1923 updates position of listframe so that no gaps at the bottom or top of the list are visible
1924 updates position of scrollbar to match what parts of the list are visible
1925--]]
1926function UpdateScrollPosition()
1927 local minPos = GetMinScroll()
1928 local maxPos = GetMaxScroll()
1929 local scrollLength = maxPos - minPos
1930
1931 local yscrollpos=math.max(math.min(ListFrame.Position.Y.Scale,maxPos),minPos)
1932 ListFrame.Position=UDim2.new(ListFrame.Position.X.Scale,ListFrame.Position.X.Offset,yscrollpos,ListFrame.Position.Y.Offset)
1933
1934 local adjustedLength = 1 - ScrollBar.Size.Y.Scale
1935 ScrollBar.Position = UDim2.new(0,0,adjustedLength - (adjustedLength * ((ListFrame.Position.Y.Scale - minPos)/scrollLength)),0)
1936end
1937
1938--[[
1939 WARNING:this is in a working state, but uses massive hacks
1940 revize when global input is available
1941 Manages scrolling of the playerlist on mouse drag
1942--]]
1943function StartDrag(entry,startx,starty)
1944 local startDragTime = tick()
1945 local stopDrag = false
1946 local openPanel = true
1947 local draggedFrame = WaitForChild(entry['Frame'],'ClickListener')
1948 local function dragExit()
1949 stopDrag = true
1950
1951 if entry['Player'] and SelectedPlayer and openPanel
1952 and entry['Player']~=LocalPlayer and SelectedPlayer.userId>1 and LocalPlayer.userId>1 then
1953 ActivatePlayerEntryPanel(entry)
1954 end
1955 end
1956 local startY = nil
1957 local StartFrame = ListFrame.Position
1958 local function dragpoll(nx,ny)
1959 if not startY then
1960 startY = AbsoluteToPercent(nx,ny).Y
1961 end
1962 local nowY = AbsoluteToPercent(nx,ny).Y
1963 debugprint('drag dist:'..Vector2.new(startx-nx,starty-ny).magnitude)
1964 if Vector2.new(startx-nx,starty-ny).magnitude>MOUSE_DRAG_DISTANCE then
1965 openPanel=false
1966 end
1967
1968 local newFrameY = math.max(math.min(StartFrame.Y.Scale + (nowY - startY),GetMaxScroll()),GetMinScroll())
1969 ListFrame.Position = UDim2.new(StartFrame.X.Scale,StartFrame.X.Offset,newFrameY,StartFrame.Y.Offset)
1970 UpdateScrollPosition()
1971 end
1972 WaitForClick(ScreenGui,dragpoll,dragExit)
1973end
1974
1975
1976function StartMinimizeDrag()
1977 Delay(0,function()
1978 local startTime=tick()
1979 debugprint('Got Click2')
1980 local stopDrag = false
1981 local function dragExit()
1982 --debugprint('undone click2')
1983 if tick()-startTime<.25 then --was click
1984 ToggleMinimize()
1985 else --was drag
1986 if (DefaultBottomClipPos >= -1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale)) then
1987 DidMinimizeDrag = false
1988 else
1989 DidMinimizeDrag = true
1990 end
1991 if IsMinimized.Value then
1992 ToggleMinimize()
1993 end
1994 end
1995 stopDrag = true
1996 end
1997 local startY = nil
1998 local StartFrame = DefaultBottomClipPos
1999 local function dragpoll(nx,ny)
2000 if not IsMinimized.Value then
2001
2002 if not startY then
2003 startY = AbsoluteToPercent(nx,ny).Y
2004 end
2005 local nowY = AbsoluteToPercent(nx,ny).Y
2006 local newFrameY
2007 newFrameY = math.min(math.max(StartFrame + (nowY - startY),-1),-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale))
2008 DefaultBottomClipPos = newFrameY
2009 UpdateMinimize()
2010 ScrollBarFrame.Size= UDim2.new(ScrollBarFrame.Size.X.Scale,0,(DefaultBottomClipPos+BottomClipFrame.Size.Y.Scale),0)
2011 ScrollBarFrame.Position= UDim2.new(ScrollBarFrame.Position.X.Scale,0,1-ScrollBarFrame.Size.Y.Scale,0)
2012 UpdateScrollBarSize()
2013 UpdateScrollPosition()
2014 UpdateScrollBarVisibility()
2015
2016 end
2017 end
2018 Spawn(function() WaitForClick(ScreenGui,dragpoll,dragExit) end)
2019 end)
2020
2021end
2022
2023 -------------------------------
2024 -- Input Callback functions
2025 -------------------------------
2026IsMaximized.Value=false
2027IsMinimized.Value=false
2028IsMaximized.Changed:connect(UpdateMaximize)
2029IsMinimized.Changed:connect(UpdateMinimize)
2030
2031ExtendButton.MouseButton1Down:connect(function()
2032 if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end
2033 LastClick = time()
2034 if IsTabified.Value then
2035 UnTabify()
2036 else
2037 StartMinimizeDrag()
2038 end
2039end)
2040
2041MaximizeButton.MouseButton1Click:connect(function()
2042 if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end
2043 LastClick = time()
2044 if IsTabified.Value then
2045 UnTabify()
2046 elseif not AreNamesExpanded.Value then
2047 AreNamesExpanded.Value = true
2048 BaseUpdate()
2049 else
2050 ToggleMaximize()
2051 end
2052end)
2053
2054MaximizeButton.MouseButton2Click:connect(function()
2055 if(time() - LastClick < ButtonCooldown) or InPopupWaitForClick then return end
2056 LastClick = time()
2057 if IsTabified.Value then
2058 UnTabify()
2059 elseif IsMaximized.Value then
2060 ToggleMaximize()
2061 elseif AreNamesExpanded.Value then
2062 AreNamesExpanded.Value = false
2063 BaseUpdate()
2064 else
2065 Tabify()
2066 end
2067end)
2068
2069
2070-------------------------------
2071-- MiddleFrames management
2072-------------------------------
2073--[[
2074 adds a background frame to the listframe
2075--]]
2076function AddMiddleBGFrame()
2077 local nBGFrame = MiddleBGTemplate:Clone()
2078 nBGFrame.Position = UDim2.new(.5,0,((#MiddleFrameBackgrounds) * nBGFrame.Size.Y.Scale),0)
2079 if (#MiddleFrameBackgrounds+1)%2 ~= 1 then
2080 if IsMaximized.Value then
2081 nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeDark']
2082 else
2083 nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midDark']
2084 end
2085 else
2086 if IsMaximized.Value then
2087 nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['LargeLight']
2088 else
2089 nBGFrame.Background.Image = 'http://www.roblox.com/asset/?id='..Images['midLight']
2090 end
2091 end
2092 nBGFrame.Parent = ListFrame
2093 table.insert(MiddleFrameBackgrounds,nBGFrame)
2094
2095 if #MiddleFrameBackgrounds<DefaultListSize and not DidMinimizeDrag then
2096 --print('readjusting bottom clip')
2097 DefaultBottomClipPos=-1+(#MiddleFrameBackgrounds*MiddleBGTemplate.Size.Y.Scale)
2098 end
2099
2100 if not IsMinimized.Value then
2101 UpdateMinimize()
2102 end
2103end
2104--[[
2105 removes a background from from the listframe
2106--]]
2107function RemoveMiddleBGFrame()
2108 MiddleFrameBackgrounds[#MiddleFrameBackgrounds]:Destroy()
2109 table.remove(MiddleFrameBackgrounds,#MiddleFrameBackgrounds)
2110 if not IsMinimized.Value then
2111 UpdateMinimize()
2112 end
2113end
2114-------------------------------
2115-- Player Callback functions
2116-------------------------------
2117local FONT_SIZES =
2118{'Size8','Size9','Size10','Size11','Size12','Size14','Size24','Size36','Size48'}
2119--[[
2120 note:should probably set to something other than mainFrame.AbsoluteSize, should work for now
2121 if textbounds ever works on textscaled, switch to that :(
2122--]]
2123function ChangeHeaderName(nname)
2124 HeaderName.Text = nname
2125 UpdateHeaderNameSize()
2126end
2127
2128--[[
2129 Will fit the player's name to the bounds of the header
2130 called on resize of the window and playedr name change events
2131 HACK: cannot use 'Textscaled' due to unable to find text bounds when scaled
2132--]]
2133function UpdateHeaderNameSize()
2134 local tHeader= HeaderName:Clone()
2135 tHeader.Position=UDim2.new(2,0,2,0)
2136 tHeader.Parent=ScreenGui
2137 local fSize=7 --Size24 in table
2138 tHeader.FontSize=FONT_SIZES[fSize]
2139 Delay(.2,function()
2140 while tHeader.TextBounds.x==0 do wait(1/30) end
2141 while tHeader.TextBounds.x-(NormalBounds.X.Offset) > 1 do
2142 fSize=fSize-1
2143 tHeader.FontSize=FONT_SIZES[fSize]
2144 wait(.2)
2145 end
2146 HeaderName.FontSize=tHeader.FontSize
2147 tHeader:Destroy()
2148 end)
2149end
2150ScreenGui.Changed:connect(UpdateHeaderNameSize)
2151
2152--[[
2153 called only when the leaderstats object is added to a given player entry
2154 removes old stats, adds any existing stats, and sets up listeners for new stats
2155 @Args:
2156 playerEntry A reference to the ENTRY(table) of the player who had leaderstats added
2157--]]
2158function LeaderstatsAdded(playerEntry)
2159 --RemoveAllStats(playerEntry)
2160 local nplayer = playerEntry['Player']
2161 for _,i in pairs(nplayer.leaderstats:GetChildren()) do
2162 StatAdded(i,playerEntry)
2163 end
2164 nplayer.leaderstats.ChildAdded:connect(function(nchild) StatAdded(nchild,playerEntry) end)
2165 nplayer.leaderstats.ChildRemoved:connect(function(nchild) StatRemoved(nchild,playerEntry) end)
2166end
2167--[[
2168 called when leaderstats object is removed from play in player entry
2169 Note: may not be needed, might be able to just rely on leaderstats added
2170 @Args:
2171 oldLeaderstats leaderstats object to be removed
2172 playerEntry A reference to the ENTRY(table) of the player
2173--]]
2174function LeaderstatsRemoved(oldLeaderstats,playerEntry)
2175 while AddingFrameLock do debugprint('waiting to insert '..playerEntry['Player'].Name) wait(1/30) end
2176 AddingFrameLock = true
2177 RemoveAllStats(playerEntry)
2178 AddingFrameLock = false
2179end
2180
2181function ClosePopUpPanel()
2182 if SelectedPlayerEntry then
2183 local tframe = SelectedPlayerEntry['Frame']
2184 Spawn(function() TweenProperty(tframe,'BackgroundTransparency',.5,1,BASE_TWEEN) end)
2185 end
2186 PopUpPanel:TweenPosition(UDim2.new(1,0,0,0), "Out", "Linear", BASE_TWEEN,true)
2187 wait(.1)
2188 InPopupWaitForClick= false
2189 SelectedPlayerEntry = nil
2190end
2191
2192--[[
2193 prepares the needed popup to be tweened on screen, and updates the position of the popup clip
2194 frame to match the selected player frame's position
2195--]]
2196function InitMovingPanel( entry, player)
2197 PopUpClipFrame.Parent= ScreenGui
2198
2199 if PopUpPanel then
2200 PopUpPanel:Destroy()
2201 end
2202 PopUpPanel= PopUpPanelTemplate:Clone()
2203 PopUpPanel.Parent= PopUpClipFrame
2204
2205 local nextIndex = 2
2206 local friendStatus = GetFriendStatus(player)
2207 debugprint (tostring(friendStatus))
2208 local showRankMenu = IsPersonalServer and LocalPlayer.PersonalServerRank >= PrivilegeLevel['Admin'] and LocalPlayer.PersonalServerRank > SelectedPlayer.PersonalServerRank
2209
2210
2211 local ReportPlayerButton = MakePopupButton(PopUpPanel,'Report Player',0)
2212 ReportPlayerButton.MouseButton1Click:connect(function() OpenAbuseDialog() end)
2213
2214 local enableFriendRequests = true
2215
2216 if enableFriendRequests then
2217 local FriendPlayerButton = MakePopupButton(PopUpPanel,'Friend',1, not showRankMenu and friendStatus~=Enum.FriendStatus.FriendRequestReceived)
2218 FriendPlayerButton.MouseButton1Click:connect(OnFriendButtonSelect)
2219
2220
2221 if friendStatus==Enum.FriendStatus.Friend then
2222 FriendPlayerButton:FindFirstChild('ButtonText').Text='UnFriend Player'
2223 elseif friendStatus==Enum.FriendStatus.Unknown or friendStatus==Enum.FriendStatus.NotFriend then
2224 FriendPlayerButton:FindFirstChild('ButtonText').Text='Send Request'
2225 elseif friendStatus==Enum.FriendStatus.FriendRequestSent then
2226 FriendPlayerButton:FindFirstChild('ButtonText').Text='Revoke Request'
2227 elseif friendStatus==Enum.FriendStatus.FriendRequestReceived then
2228 FriendPlayerButton:FindFirstChild('ButtonText').Text='Accept Friend'
2229 local FriendRefuseButton = MakePopupButton(PopUpPanel,'Decline Friend',2,not showRankMenu)
2230 FriendRefuseButton.MouseButton1Click:connect(OnFriendRefuseButtonSelect)
2231 nextIndex=nextIndex+1
2232 end
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
2727LocalPlayer.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--]]
2972game.GuiService:AddKey("\t")
2973local LastTabTime = time()
2974game.GuiService.KeyPressed:connect(
2975function(key)
2976 if key == "\t" then
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
2998end)
2999
3000
3001function PlayersChildAdded(tplayer)
3002 if tplayer:IsA('Player') then
3003 Spawn(function() debugPlayerAdd(tplayer) end)
3004 else
3005 BlowThisPopsicleStand()
3006 end
3007end
3008
3009function coreGuiChanged(coreGuiType, enabled)
3010 if coreGuiType == Enum.CoreGuiType.All or coreGuiType == Enum.CoreGuiType.PlayerList then
3011 MainFrame.Visible = enabled
3012 end
3013end
3014
3015function TeamsChildAdded(nteam)
3016 if nteam:IsA('Team') then
3017 TeamAdded(nteam)
3018 else
3019 BlowThisPopsicleStand()
3020 end
3021end
3022
3023function TeamsChildRemoved(nteam)
3024 if nteam:IsA('Team') then
3025 TeamRemoved(nteam)
3026 else
3027 BlowThisPopsicleStand()
3028 end
3029end
3030
3031 ----------------------------
3032 -- Hookups and initialization
3033 ----------------------------
3034function debugPlayerAdd(p)
3035 InsertPlayerFrame(p)
3036end
3037
3038pcall(function()
3039 coreGuiChanged(Enum.CoreGuiType.PlayerList, Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.PlayerList))
3040 Game.StarterGui.CoreGuiChangedSignal:connect(coreGuiChanged)
3041end)
3042
3043while not game:GetService('Teams') do wait(1/30) debugprint('Waiting For Teams') end
3044for _,i in pairs(game.Teams:GetTeams()) do TeamAdded(i) end
3045for _,i in pairs(Players:GetPlayers()) do Spawn(function() debugPlayerAdd(i) end) end
3046
3047game.Teams.ChildAdded:connect(TeamsChildAdded)
3048game.Teams.ChildRemoved:connect(TeamsChildRemoved)
3049Players.ChildAdded:connect(PlayersChildAdded)
3050
3051InitReportAbuse()
3052AreNamesExpanded.Value = true
3053BaseUpdate()
3054
3055
3056
3057--UGGGLY,find a better way later
3058wait(2)
3059IsPersonalServer= not not game.Workspace:FindFirstChild("PSVariable")
3060
3061 ----------------------------
3062 -- Running Logic
3063 ----------------------------
3064
3065 --debug stuffs, will only run for 'newplayerlistisbad'
3066 if LocalPlayer.Name == 'newplayerlistisbad' or LocalPlayer.Name == 'imtotallyadmin' then
3067 debugFrame.Parent = ScreenGui
3068 Spawn(function()
3069 while true do
3070 local str_players=''
3071 for _,i in pairs(game.Players:GetPlayers()) do
3072 str_players= str_players .." " .. i.Name
3073 end
3074 debugplayers.Text=str_players
3075 wait(.5)
3076 end
3077 end)
3078 end