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