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