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 |