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