View difference between Paste ID: RVQraWCF and cwXB2wRv
SHOW: | | - or go back to the newest paste.
1
local RunService = game:service'RunService'
2
script.Parent=nil;
3
local Camera = Workspace.CurrentCamera or nil
4
local Lighting = game.Lighting
5
local Player = game.Players.LocalPlayer or game.Players.SmokeDelsin
6
local UserInterface = game:service'UserInputService'
7
local RF = game.ReplicatedStorage:findFirstChild("GKAttachment") or nil
8
local bannedlist = {"21506048","Dontnukeme"};
9
local changecamonpossess = false
10
local Debris = game:service'Debris'
11
local Mouse = Player:GetMouse() or nil
12
local Players = game.Players
13
local chatAdornee = Player.Character.Head
14
local RbxUtility = LoadLibrary("RbxUtility")
15
local CMDS = {};
16
local InsertService = game:service'InsertService'
17
local math = {
18
    abs = math.abs,
19
    acos = math.acos,
20
    asin = math.asin,
21
    atan = math.atan,
22
    atan2 = math.atan2,
23
    ceil = math.ceil,
24
    cos = math.cos,
25
    cosh = math.cosh,
26
    deg = math.deg,
27
    exp = math.exp,
28
    floor = math.floor,
29
    fmod = math.fmod,
30
    frexp = math.frexp,
31
    huge = math.huge,
32
    ldexp = math.ldexp,
33
    log = math.log,
34
    log10 = math.log10,
35
    max = math.max,
36
    min = math.min,
37
    modf = math.modf,
38
    phi = 1.618033988749895,
39
    pi = math.pi,
40
    pow = math.pow,
41
    rad = math.rad,
42
    random = math.random,
43
    randomseed = math.randomseed,
44
    sin = math.sin,
45
    sinh = math.sinh,
46
    sqrt = math.sqrt,
47
    tan = math.tan,
48
    tanh = math.tanh,
49
    tau = 2 * math.pi
50
}
51
52
53
TaskScheduler = {};
54
55
local currentTime = 0
56
local pairs = pairs
57
local rbx_coroutine_create = coroutine.create
58
local rbx_coroutine_resume = coroutine.resume
59
local rbx_Wait = Wait
60
local rbx_ypcall = ypcall
61
local threads, swapThreads = {}, {}
62
local function StartCoroutine(func, delay, ...)
63
        if delay > 0 then
64
                rbx_Wait(delay)
65
        end
66
        local success, message = rbx_ypcall(func, ...)
67
        if not success then
68
                print("Error in a TaskScheduler coroutine: "..message)
69
        end
70
end
71
function TaskScheduler.GetCurrentTime()
72
        return currentTime
73
end
74
function TaskScheduler.MainLoop(stepTime)
75
        currentTime = currentTime + stepTime
76
        threads, swapThreads = swapThreads, threads
77
        local threshold = -0.5 * stepTime
78
        for thread, resumeTime in pairs(swapThreads) do
79
                local remainingTime = currentTime - resumeTime
80
                if remainingTime >= threshold then
81
                        swapThreads[thread] = nil
82
                        local success, message = coroutine.resume(thread, remainingTime, currentTime)
83
                        if not success then
84
                                print("Error in a TaskScheduler custom thread: "..message)
85
                        end
86
                end
87
        end
88
        threads, swapThreads = swapThreads, threads
89
        for thread, resumeTime in pairs(swapThreads) do
90
                threads[thread], swapThreads[thread] = resumeTime, nil
91
        end
92
end
93
-- TODO: add stack trace info to scheduling functions?
94
function TaskScheduler.Schedule(t, f, ...)
95
        coroutine.resume(coroutine.create(StartCoroutine), f, t, ...)
96
end
97
function TaskScheduler.Start(f, ...)
98
        coroutine.resume(coroutine.create(StartCoroutine), f, 0, ...)
99
end
100
function TaskScheduler.ScheduleCustomThread(t, f)
101
        threads[coroutine.create(f)] = currentTime + t
102
end
103
function TaskScheduler.Wait(duration)
104
        duration = tonumber(duration) or 0
105
        threads[coroutine.running()] = currentTime + duration
106
        local remainingTime, currentTime = coroutine.yield()
107
        return remainingTime + duration, currentTime
108
end
109
local success, player = Players.LocalPlayer
110
if success and player then
111
        RunService.RenderStepped:connect(function()
112
                TaskScheduler.MainLoop(1 / 60)
113
        end)
114
else
115
        RunService.Stepped:connect(function()
116
                TaskScheduler.MainLoop(1 / 30)
117
        end)
118
end
119
120
ChatBubble = {};
121
122
local FONT_CUSTOM_A_SRC, FONT_CUSTOM_A, TextAlignment, LoadFixedFont, LoadFont, DrawTextNetwork, DrawMultilineTextNetwork, ConfigureChatBubble,
123
 
124
CreateChatBubble, WrapText, chat_bubbles
125
FONT_CUSTOM_A_SRC = "03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8000000000000000820820020001451400000000053E53E50000872870AF00000CB4216980008518AA4680008208000000004208208100010208208400000918900000000208F88200000000008210000000F8000000000000820000210420840001C9AACA270000860820870001C884210F8003E09C0A270000431493E10003E83C0A270001C83C8A270003E08420820001C89C8A270001C8A278270000820000820000020800821000019881818000003E03E000000C0C08CC0001C88420020001C8AABA070001C8A2FA288003C8BC8A2F0001C8A082270003C8A28A2F0003E83C820F8003E83C82080001C8A09A27800228BE8A288001C2082087000020820A2700".."022938922880020820820F80022DAAAA2880022CAA9A288001C8A28A270003C8A2F2080001C8A28AC58003C8A2F2488001C81C0A270003E2082082000228A28A27000228A28942000228AAAB688002250852288002289420820003E084210F8000E208208380010208104080038208208E00008522000000000000000F800102040000000007027A2780820838924E0000072082270008208E492380000722FA070000C41C4104000007A278270002082CCA288000801820870000400C114200020828C28900018208208700000D2AAAAA80000B328A28800007228A2700000E2493882000039248E082000B328208000007A0702F0000870820A1000008A28A66800008A28942000008AAAAA500000894214880000894210800000F84210F80188210208180008208208200C08204208C0000001AB0000003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80".."03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80".."03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80"
126
FONT_CUSTOM_A = {}
127
128
ChatBubble.THEME = {}
129
ChatBubble.THEME.AQUA = {
130
        Name = "Aqua",
131
        Background = Color3.new(0, 1 / 3, 0.5),
132
        Foreground = Color3.new(2 / 3, 1, 1)
133
}
134
ChatBubble.THEME.CLASSIC = {
135
        Name = "Classic",
136
        Background = Color3.new(0, 0, 0),
137
        Foreground = Color3.new(1, 1, 1)
138
}
139
140
ChatBubble.THEME.KAYAVEN = {
141
        Name = "Kayaven",
142
        Background = Color3.new(0, 0, 0),
143
        Foreground = Color3.new(0, 1, 0)
144
}
145
ChatBubble.THEME.CRIMSON = {
146
        Name = "Crimson",
147
        Background = Color3.new(0, 0, 0),
148
        Foreground = Color3.new(0.9, 0, 0)
149
}
150
ChatBubble.THEME.GRAPE = {
151
        Name = "Grape",
152
        Background = Color3.new(0.25, 0, 0.25),
153
        Foreground = Color3.new(1, 2 / 3, 1)
154
}
155
ChatBubble.THEME.LIBERATION = {
156
        Name = "Liberation",
157
        Background = Color3.new(1 / 6, 3 / 7, 3 / 7),
158
        Foreground = Color3.new(1, 1, 1)
159
}
160
ChatBubble.THEME.PASSION = {
161
        Name = "Passion",
162
        Background = Color3.new(0.5, 0, 0),
163
        Foreground = Color3.new(1, 1, 1)
164
}
165
ChatBubble.THEME.PURPLE = {
166
        Name = "Purple",
167
        Background = Color3.new(0.25, 0, 0.25),
168
        Foreground = Color3.new(1, 1, 1)
169
}
170
ChatBubble.THEME.RAINBOW = {
171
        Name = "Rainbow",
172
        Background = function(bubble_info)
173
                local billboard, frame = bubble_info[5], bubble_info[6]
174
                TaskScheduler.Start(function()
175
                        while billboard:IsDescendantOf(Workspace) do
176-
                                local red, green, blue = Utility.GetRainbowRGB(tick())
176+
                                local black, white, grey = Utility.GetRainbowRGB(tick())
177
                                frame.BackgroundColor3 = Color3.new(0.6 * red, 0.6 * green, 0.65 * blue)
178
                                RunService.Stepped:wait()
179
                        end
180
                end)
181
        end,
182
        Foreground = Color3.new(1, 1, 1)
183
}
184
ChatBubble.THEME.TEAL = {
185
        Name = "Teal",
186
        Background = Color3.new(0, 1 / 3, 0.5),
187
        Foreground = Color3.new(1, 1, 1)
188
}
189
 
190
function ChatBubble.GetTheme()
191
        return ChatBubble.theme_info
192
end
193
function ChatBubble.SetTheme(theme_info)
194
        if type(theme_info) == "string" then
195
                theme_info = string.lower(theme_info)
196
                for key, info in pairs(ChatBubble.THEME) do
197
                        if info.Name:lower() == theme_info:lower() then
198
                                ChatBubble.SetTheme(info)
199
                                break
200
                        end
201
                end
202
                return
203
        end
204
        ChatBubble.theme_info = theme_info
205
        ChatBubble.background_color = theme_info.Background
206
        ChatBubble.font = LoadFont(ChatBubble.FONT_DEFAULT, theme_info.Foreground)
207
        print("Theme has been set to "..theme_info.Name.." in ChatBubble")
208
end
209
 
210
do
211
local floor = math.floor
212
local max = math.max
213
local asc = string.byte
214
local chr = string.char
215
local find = string.find
216
local gmatch = string.gmatch
217
local sub = string.sub
218
local insert = table.insert
219
local type = type
220
local unpack = unpack
221
 
222
local PopIntegerBit
223
 
224
TextAlignment = setmetatable({
225
        [0] = 0,
226
        [1] = 1,
227
        [2] = 2,
228
        Left = 0,
229
        Center = 1,
230
        Right = 2
231
}, {
232
        __call = function(self, ...)
233
                local argc = #{...}
234
                if argc == 0 then
235
                        return 0
236
                else
237
                        local arg = (...)
238
                        local value = rawget(self, arg)
239
                        if value then
240
                                return value
241
                        else
242
                                local arg_type = type(arg)
243
                                error("Invalid value" .. ((arg_type == "number") and (" " .. arg) or ((arg_type == "string") and (" \"" .. arg .. "\"") or
244
 
245
"")) .. " for enum TextAlignment")
246
                        end
247
                end
248
        end
249
})
250
 
251
function PopIntegerBit(value, bit)
252
        if value >= bit then
253
                return 1, value - bit
254
        else
255
                return 0, value
256
        end
257
end
258
function LoadFixedFont(dest, src, height, width)
259
        local n = #src / 64 - 1
260
        local bit_index = 0
261
        local symbol_bits = width * height
262
        for i = 0, 255 do
263
                local char_data = {}
264
                for j = 1, height do
265
                        char_data[j] = {}
266
                end
267
                dest[i] = char_data
268
        end
269
        for i = 1, #src do
270
                local buffer = tonumber(sub(src, i, i), 16)
271
                for j = 1, 4 do
272
                        local code = floor(bit_index / symbol_bits)
273
                        local row = floor(bit_index / width) % height + 1
274
                        local column = bit_index % width + 1
275
                        dest[code][row][column], buffer = PopIntegerBit(buffer, 8)
276
                        buffer = buffer * 2
277
                        bit_index = bit_index + 1
278
                end
279
        end
280
end
281
function LoadFont(font_data, color)
282
        local font_obj = {}
283
        for character, char_data in pairs(font_data) do
284
                local code = character
285
                if type(code) ~= "number" then
286
                        code = asc(character)
287
                end
288
                local height = #char_data
289
                local width = #char_data[1]
290
                local pixel_h = 1 / height
291
                local pixel_w = 1 / width
292
                local pixel_size = UDim2.new(pixel_w, 0, pixel_h, 0)
293
                local frame = Instance.new("Frame")
294
                frame.BackgroundTransparency = 1
295
                frame.Name = ""
296
                for y = 1, height do
297
                        local row = char_data[y]
298
                        for x = 1, width do
299
                                local opacity = row[x]
300
                                if opacity ~= 0 then
301
                                        local pixel = Instance.new("Frame", frame)
302
                                        pixel.BackgroundColor3 = color
303
                                        pixel.BorderSizePixel = 0
304
                                        pixel.Name = ""
305
                                        pixel.Position = UDim2.new(x * pixel_w, 0, y * pixel_h, 0) - pixel_size
306
                                        pixel.Size = pixel_size -- + UDim2.new(0, 0, 0, 1) -- correction
307
                                        -- ^ never mind that correction, fixed by changing font size to 12x16 instead of 13x17
308
                                        if opacity then
309
                                                pixel.BackgroundTransparency = 1 - opacity
310
                                        end
311
                                end
312
                        end
313
                end
314
                font_obj[code] = {frame, height, width}
315
        end
316
        return font_obj
317
end
318
function DrawTextNetwork(text, font, size, delay_offset)
319
        if #text == 0 then
320
                text = " "
321
        end
322
        local frame = Instance.new("Frame")
323
        frame.BackgroundTransparency = 1
324
        frame.BorderSizePixel = 0
325
        local objects = {}
326
        local length = #text
327
        local height = 0
328
        local width = 0
329
        for i = 1, length do
330
                local character = sub(text, i, i)
331
                local code = asc(character)
332
                local char_data = assert(font[code] or FONT_SYMBOL_MISSING, "FONT ERROR: '" .. character .. "' (" .. code .. ") not found")
333
                local char_proto, char_h, char_w = unpack(char_data)
334
                objects[i] = char_data
335
                height = max(char_h, height)
336
                width = width + char_w
337
        end
338
        local offset = 0
339
        local punctuation_delay = 0
340
        for i = 1, length do
341
                delay(delay_offset + (i + punctuation_delay - 1) / 30, function()
342
                        local char_data = objects[i]
343
                        local char_proto, char_h, char_w = unpack(char_data)
344
                        local char_obj = char_proto:Clone()
345
                        char_obj.Position = UDim2.new(offset / width, 0, 0, 0)
346
                        char_obj.Size = UDim2.new(char_w / width, 0, 1, 0)
347
                        char_obj.Parent = frame
348
                        offset = offset + char_w
349
                end)
350
                local character = sub(text, i, i)
351
                if character == "." then
352
                        punctionation_delay = punctuation_delay + 3
353
                elseif character == "?" or character == "!" then
354
                        punctionation_delay = punctuation_delay + 2
355
                elseif character == ";" or character == "~" then
356
                        punctionation_delay = punctuation_delay + 1
357
                end
358
        end
359
        local ratio = (height == 0) and (0) or (width / height)
360
        frame.Size = UDim2.new(size.X.Scale * ratio, size.X.Offset * ratio, size.Y.Scale, size.Y.Offset)
361
        return frame, height, width, (length + punctuation_delay) / 30
362
end
363
function DrawMultilineTextNetwork(text, font, size, delay_offset, ...)
364
        local align = TextAlignment(...)
365
        local frame = Instance.new("Frame")
366
        frame.BackgroundTransparency = 1
367
        frame.BorderSizePixel = 0
368
        local height = 0
369
        local width = 0
370
        local objects = {}
371
        for line in gmatch(text .. "\n", "([^\n]*)\n") do
372
                local line_obj, line_h, line_w, line_delay = DrawTextNetwork(line, font, size, delay_offset)
373
                insert(objects, {line_obj, line_h, line_w})
374
                height = height + line_h
375
                width = max(line_w, width)
376
                delay_offset = delay_offset + line_delay
377
        end
378
        local offset = 0
379
        for index, line_data in ipairs(objects) do
380
                local line_obj, line_h, line_w = unpack(line_data)
381
                local align_offset
382
                if align == TextAlignment.Left then
383
                        align_offset = 0
384
                elseif align == TextAlignment.Center then
385
                        align_offset = 0.5 - line_w / width / 2
386
                elseif align == TextAlignment.Right then
387
                        align_offset = 1 - line_w / width
388
                end
389
                line_obj.Position = UDim2.new(align_offset, 0, offset / height, 0)
390
                line_obj.Parent = frame
391
                offset = offset + line_h
392
        end
393
        local line_count = #objects
394
        local ratio = (height == 0) and (0) or (line_count * width / height)
395
        frame.Size = UDim2.new(size.X.Scale * ratio, size.X.Offset * ratio, size.Y.Scale * line_count, size.Y.Offset * line_count)
396
        return frame, height, width
397
end
398
end
399
 
400
LoadFixedFont(FONT_CUSTOM_A, FONT_CUSTOM_A_SRC, 8, 6)
401
ChatBubble.FONT_DEFAULT = FONT_CUSTOM_A
402
ChatBubble.SetTheme("Rainbow")
403
 
404
chat_bubbles = {}
405
 
406
function CreateChatBubble(bubble_info)
407
        local creation_time, text, backup = bubble_info[1], bubble_info[2], bubble_info[8]
408
        local billboard, frame, label
409
        if backup and false then
410
                billboard = backup:Clone()
411
                frame = billboard.Frame
412
                label = frame.Label
413
                bubble_info[5] = billboard
414
                bubble_info[6] = frame
415
                bubble_info[7] = label
416
                billboard.Parent = Workspace
417
        else
418
                label = DrawMultilineTextNetwork(text, bubble_info[9], UDim2.new(0, 12, 0, 16), creation_time - time(), "Center")
419
                label.Name = "Label"
420
                label.Position = UDim2.new(0, 16, 0, 16)
421
                billboard = Instance.new("BillboardGui", Workspace)
422
                billboard.Adornee = chatAdornee
423
                billboard.AlwaysOnTop = true
424
                billboard.Size = UDim2.new(label.Size.X.Scale, label.Size.X.Offset + 32, label.Size.Y.Scale, label.Size.Y.Offset + 32)
425
                billboard.SizeOffset = Vector2.new(0, 0)
426
                billboard.StudsOffset = Vector3.new(0, 1, 0)
427
                frame = Instance.new("Frame", billboard)
428
                bubble_info[5] = billboard
429
                bubble_info[6] = frame
430
                bubble_info[7] = label
431
                local background_color = bubble_info[10]
432
                if type(background_color) == "function" then
433
                        background_color(bubble_info)
434
                else
435
                        frame.BackgroundColor3 = background_color
436
                end
437
                frame.BackgroundTransparency = 0.3
438
                frame.BorderSizePixel = 0
439
                frame.ClipsDescendants = true
440
                frame.Name = "Frame"
441
                frame.Size = UDim2.new(1, 0, 0, 0)
442
                label.Parent = frame
443
                -- bubble_info[8] = billboard:Clone()
444
        end
445
end
446
local tween_time = 0.3
447
function ConfigureChatBubble(bubble_info)
448
        local creation_time, destruction_time, billboard, frame = bubble_info[1], bubble_info[3], bubble_info[5], bubble_info[6]
449
        if not billboard or billboard.Parent ~= workspace then
450
                CreateChatBubble(bubble_info)
451
                billboard, frame = bubble_info[5], bubble_info[6]
452
        end
453
        if billboard.Adornee ~= chatAdornee then
454
                billboard.Adornee = chatAdornee
455
        end
456
        local current_time = time()
457
        local elapsed_time = current_time - creation_time
458
        local remaining_time = destruction_time - current_time
459
        if remaining_time < 0 then
460
                bubble_info[4] = false
461
                billboard:Destroy()
462
                return false
463
        elseif remaining_time < tween_time then
464
                local tween_progress = math.sin(remaining_time * math.pi / (tween_time * 2))
465
                frame.Size = UDim2.new(1, 0, tween_progress, 0)
466
        elseif elapsed_time < tween_time then
467
                local tween_progress = math.sin(elapsed_time * math.pi / (tween_time * 2))
468
                frame.Size = UDim2.new(1, 0, tween_progress, 0)
469
        elseif frame.Size ~= UDim2.new(1, 0, 1, 0) then
470
                frame.Size = UDim2.new(1, 0, 1, 0)
471
        end
472
        return true
473
end
474
function ChatBubble.MainLoop()
475
        local offset = 0
476
        local removing = {}
477
        for index, bubble_info in ipairs(chat_bubbles) do
478
                if not ConfigureChatBubble(bubble_info) then
479
                        removing[#removing + 1] = index - #removing
480
                else
481
                        local billboard, frame = bubble_info[5], bubble_info[6]
482
                        local billboard_h = billboard.Size.Y.Offset
483
                        local bubble_h = frame.Size.Y.Scale * billboard_h
484
                        offset = 8 + offset + bubble_h
485
                        billboard.SizeOffset = Vector2.new(0, offset / billboard_h - 0.5)
486
                end
487
        end
488
        for index, bubble_index in ipairs(removing) do
489
                table.remove(chat_bubbles, bubble_index)
490
        end
491
        RunService.Stepped:wait()
492
end
493
function WrapText(text, character_limit, line_length_limit)
494
        if #text > character_limit then
495
                text = string.sub(text, 1, character_limit - 3) .. "..."
496
        end
497
        local text_length = #text
498
        local line_length = 0
499
        local i = 0
500
        while i <= text_length do
501
                i = i + 1
502
                local character = string.sub(text, i, i)
503
                if character == "\t" then
504
                        local tabulation_size = 4 - line_length % 4
505
                        line_length = line_length + tabulation_size
506
                        if line_length >= line_length_limit then
507
                                tabulation_size = line_length - line_length_limit
508
                                line_length = 0
509
                                text_length = text_length + tabulation_size
510
                                text = string.sub(text, 1, i - 1) .. string.rep(" ", tabulation_size) .. "\n" .. string.sub(text, i + 1)
511
                                i = i + tabulation_size + 1
512
                        else
513
                                text_length = text_length + tabulation_size - 1
514
                                text = string.sub(text, 1, i - 1) .. string.rep(" ", tabulation_size) .. string.sub(text, i + 1)
515
                                i = i + tabulation_size - 1
516
                        end
517
                elseif character == "\n" then
518
                        line_length = 0
519
                else
520
                        line_length = line_length + 1
521
                        if line_length >= line_length_limit then
522
                                local k = i - line_length + 1
523
                                local success = false
524
                                for j = i, k, -1 do
525
                                        if string.match(string.sub(text, j, j), "[ \t]") then
526
                                                text = string.sub(text, 1, j - 1) .. "\n" .. string.sub(text, j + 1)
527
                                                text_length = text_length + 1
528
                                                success = true
529
                                                break
530
                                        end
531
                                end
532
                                if not success then
533
                                        text = string.sub(text, 1, i) .. "\n" .. string.sub(text, i + 1)
534
                                        text_length = text_length + 1
535
                                end
536
                                i = i + 1
537
                                line_length = 0
538
                        end
539
                end
540
        end
541
        if #text > character_limit then
542
                text = string.sub(text, 1, character_limit - 3) .. "..."
543
        end
544
        return text
545
end
546
function ChatBubble.Create(text, theme)
547
        local text = WrapText(text, 200, 30)
548
        local creation_time = time()
549
        local bubble_info = {creation_time, text, creation_time + 6 + #text / 15, true}
550
        local previousTheme
551
        if theme then
552
                previousTheme = ChatBubble.GetTheme()
553
                ChatBubble.SetTheme(theme)
554
        end
555
        bubble_info[9] = ChatBubble.font
556
        bubble_info[10] = ChatBubble.background_color
557
        if previousTheme then
558
                ChatBubble.SetTheme(previousTheme)
559
        end
560
        table.insert(chat_bubbles, 1, bubble_info)
561
end
562
TaskScheduler.Start(function()
563
        while true do
564
                ChatBubble.MainLoop()
565
        end
566
end)
567
568
PyramidCharacter = {};
569
570
local stock_triangle = Instance.new("WedgePart")
571
stock_triangle.Anchored = true
572
stock_triangle.BottomSurface = "Smooth"
573
stock_triangle.FormFactor = "Custom"
574
stock_triangle.Locked = true
575
stock_triangle.TopSurface = "Smooth"
576
local stock_triangle_mesh = Instance.new("SpecialMesh", stock_triangle)
577
stock_triangle_mesh.MeshType = "Wedge"
578
local triangles = {}
579
function PyramidCharacter.CreateTriangle(v1, v2, v3, properties, parent, index)
580
        local triangleInfo = triangles[index]
581
        local side1 = (v1 - v2).magnitude
582
        local side2 = (v2 - v3).magnitude
583
        local side3 = (v3 - v1).magnitude
584
        local sqrside1 = side1 * side1
585
        local sqrside2 = side2 * side2
586
        local sqrside3 = side3 * side3
587
        if sqrside3 + sqrside1 == sqrside2 then
588
                v1, v2, v3 = v1, v2, v3
589
        elseif sqrside1 + sqrside2 == sqrside3 then
590
                v1, v2, v3 = v2, v3, v1
591
        elseif sqrside2 + sqrside3 == sqrside1 then
592
                v1, v2, v3 = v3, v1, v2
593
        elseif sqrside1 >= sqrside2 and sqrside1 >= sqrside3 then
594
                v1, v2, v3 = v1, v2, v3
595
        elseif sqrside2 >= sqrside3 and sqrside2 >= sqrside1 then
596
                v1, v2, v3 = v2, v3, v1
597
        else
598
                v1, v2, v3 = v3, v1, v2
599
        end
600
        local model, part1, part2, mesh1, mesh2
601
        if triangleInfo then
602
                model, part1, part2, mesh1, mesh2 = unpack(triangleInfo)
603
                if not (model.Parent == parent and part1.Parent == model and part2.Parent == model and mesh1.Parent == part1 and mesh2.Parent == part2) then
604
                        if model.Parent then
605
                                model:Destroy()
606
                        end                    
607
                        model = nil
608
                end
609
        else
610
                triangleInfo = {}
611
                triangles[index] = triangleInfo
612
        end
613
        if not model then
614
                model = Instance.new("Model")
615
                part1 = stock_triangle:Clone()
616
                part2 = stock_triangle:Clone()
617
                mesh1 = part1.Mesh
618
                mesh2 = part2.Mesh
619
                part1.Parent = model
620
                part2.Parent = model
621
                triangleInfo[1] = model
622
                triangleInfo[2] = part1
623
                triangleInfo[3] = part2
624
                triangleInfo[4] = mesh1
625
                triangleInfo[5] = mesh2
626
        end
627
        for key, value in pairs(properties) do
628
                part1[key] = value
629
                part2[key] = value
630
        end
631
        local cframe = CFrame.new(v1, v2)
632
        local relpos = cframe:pointToObjectSpace(v3)
633
        cframe = cframe * CFrame.fromEulerAnglesXYZ(0, 0, -math.atan2(relpos.x, relpos.y))
634
        local rel1 = cframe:pointToObjectSpace(v1)
635
        local rel2 = cframe:pointToObjectSpace(v2)
636
        local rel3 = cframe:pointToObjectSpace(v3)
637
        local height = rel3.y
638
        local width1 = rel3.z
639
        local width2 = rel2.z - rel3.z
640
        local relcenter1 = Vector3.new(0, height / 2, width1 / 2)
641
        local center1 = cframe:pointToWorldSpace(relcenter1)
642
        local relcenter2 = Vector3.new(0, height / 2, width2 / 2 + width1)
643
        local center2 = cframe:pointToWorldSpace(relcenter2)
644
        height = math.abs(height)
645
        width1 = math.abs(width1)
646
        width2 = math.abs(width2)
647
        if not part1.Anchored then
648
                part1.Anchored = true
649
        end
650
        part1.Size = Vector3.new(0.2, height, width1)
651
        part1.CFrame = cframe * CFrame.fromEulerAnglesXYZ(0, math.pi, 0) - cframe.p + center1  
652
        mesh1.Scale = Vector3.new(0, height / part1.Size.y, width1 / part1.Size.z)
653
        if not part2.Anchored then
654
                part2.Anchored = true
655
        end
656
        part2.Size = Vector3.new(0.2, height, width1)
657
        part2.CFrame = cframe - cframe.p + center2
658
        mesh2.Scale = Vector3.new(0, height / part1.Size.y, width2 / part2.Size.z)
659
        model.Parent = parent
660
        return model
661
end
662
PyramidCharacter.head_properties = {BrickColor = BrickColor.new(Color3.new(1, 1, 1)), Transparency = 0.5}
663
PyramidCharacter.head_radius = math.pi
664
PyramidCharacter.center = CFrame.new(0, 10, 0)
665
PyramidCharacter.point1 = Vector3.new()
666
PyramidCharacter.point2 = Vector3.new()
667
PyramidCharacter.point3 = Vector3.new()
668
PyramidCharacter.point4 = Vector3.new()
669
PyramidCharacter.core_mesh_scale = Vector3.new(0.833, 0.833, 0.833)
670
PyramidCharacter.visible = false
671
function PyramidCharacter.Teleport(location)
672
        PyramidCharacter.point1 = location
673
        PyramidCharacter.point2 = location
674
        PyramidCharacter.point3 = location
675
        PyramidCharacter.point4 = location
676
end
677
local stock_core = Instance.new("Part")
678
stock_core.Anchored = true
679
stock_core.BottomSurface = "Smooth"
680
stock_core.Color = Color3.new(1, 1, 1)
681
stock_core.FormFactor = "Custom"
682
stock_core.Locked = true
683
stock_core.Name = "CubePyramid"
684
stock_core.Size = Vector3.new(0.5, 0.5, 0.5)
685
stock_core.TopSurface = "Smooth"
686
PyramidCharacter.stock_core = stock_core
687
PyramidCharacter.core = stock_core:Clone()
688
PyramidCharacter.Archivable = false
689
PyramidCharacter.core_mesh = Instance.new("BlockMesh", core)
690
PyramidCharacter.core_lights = {}
691
PyramidCharacter.coreLightCount = 1
692
for index = 1, PyramidCharacter.coreLightCount do
693
        PyramidCharacter.core_lights[index] = Instance.new("PointLight", core)
694
end
695
PyramidCharacter.camera_distance = (Camera.Focus.p - Camera.CoordinateFrame.p).magnitude
696
PyramidCharacter.camera_position = Vector3.new()
697
Camera.Changed:connect(function(property)
698
        if PyramidCharacter.visible then
699
                if property == "CoordinateFrame" then
700
                        local cframe, focus = Camera.CoordinateFrame, Camera.Focus
701
                        local eventTime = time()
702
                        local connection
703
                        connection = Camera.Changed:connect(function()
704
                                connection:disconnect()
705
                                if eventTime == time() and Camera.Focus ~= focus then
706
                                        local camera_distance = PyramidCharacter.camera_distance
707
                                        Camera.Focus = Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)
708
                                        PyramidCharacter.camera_position = (Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)).p
709
                                end
710
                        end)
711
                        coroutine.yield()
712
                        if Camera.Focus == focus then
713
                                PyramidCharacter.camera_distance = (focus.p - cframe.p).magnitude
714
                        else
715
                                local camera_distance = PyramidCharacter.camera_distance
716
                                Camera.Focus = Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)
717
                                PyramidCharacter.camera_position = (Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)).p
718
                        end
719
                        if connection.connected then
720
                                connection:disconnect()
721
                        end
722
                end
723
        end
724
end)
725
function PyramidCharacter.Animate()
726
        local total_time = time()
727
        local core = PyramidCharacter.core
728
        local frame = PyramidCharacter.frame
729
        if PyramidCharacter.visible then
730
                local core_mesh = PyramidCharacter.core_mesh
731
                local core_lights = PyramidCharacter.core_lights
732
                if not frame or frame.Parent ~= core then
733
                        frame = Instance.new("Model")
734
                        frame.Archivable = false
735
                        frame.Parent = core
736
                        PyramidCharacter.frame = frame
737
                end
738
                if core.Parent ~= Workspace then
739
                        core = PyramidCharacter.stock_core:Clone()
740
                        PyramidCharacter.core = core
741
                        core.Archivable = false
742
                        core.Parent = Workspace
743
                        chatAdornee = core
744
                end
745
                if core_mesh.Parent ~= core then
746
                        core_mesh = Instance.new("BlockMesh", core)
747
                        PyramidCharacter.core_mesh = core_mesh
748
                end
749
                for index, core_light in ipairs(core_lights) do
750
                        if core_light.Parent ~= core then
751
                                core_light = Instance.new("PointLight", core)
752
                                core_lights[index] = core_light
753
                        end
754
                        local vertexColor = Vector3.new(Utility.GetRainbowRGB(total_time)) * 0.25 + Vector3.new(1, 1, 1) * 0.75
755
                        core_light.Color = Color3.new(vertexColor.X, vertexColor.Y, vertexColor.Z)
756
                        core_light.Brightness = 0.85 + 0.15 * math.random()
757
                        if core_light.Range ~= 30 then
758
                                core_light.Range = 30
759
                        end
760
                        if not core_light.Shadows then
761
                                core_light.Shadows = true
762
                        end
763
                end
764
                if core_mesh.Offset ~= Vector3.new(0, 0, 0) then
765
                        core_mesh.Offset = Vector3.new(0, 0, 0)
766
                end
767
                if not core.Anchored then
768
                        core.Anchored = true
769
                end
770
                if core.Transparency ~= 0 then
771
                        core.Transparency = 0
772
                end
773
                local core_mesh_scale = PyramidCharacter.core_mesh_scale
774
                local transition_speed = (math.sin(total_time * math.tau) + 1) / 16
775
                core_mesh_scale = core_mesh_scale * (1 - transition_speed) + Vector3.new(math.random() * 0.5 + 0.5, math.random() * 0.5 + 0.5, math.random()
776
 
777
* 0.5 + 0.5) * transition_speed
778
                core_mesh.Scale = core_mesh_scale * 2
779
                local center = CFrame.new(PyramidCharacter.camera_position) * CFrame.Angles(0, total_time * math.tau, 0)
780
                local cframe1 = CFrame.new(PyramidCharacter.head_radius, 0, 0)
781
                local cframe2 = CFrame.Angles(math.tau / -3, 0, 0)
782
                local cframe3 = CFrame.Angles(0, math.tau / 3, 0)
783
                local cframe4 = center * cframe3               
784
                local desired1 = center * CFrame.new(0, PyramidCharacter.head_radius, 0)
785
                local desired2 = center * cframe2 * cframe1
786
                local desired3 = cframe4 * cframe2 * cframe1
787
                local desired4 = cframe4 * cframe3 * cframe2 * cframe1
788
                local point1 = (PyramidCharacter.point1 * 3 + desired1.p) / 4
789
                local point2 = (PyramidCharacter.point2 * 3 + desired2.p) / 4
790
                local point3 = (PyramidCharacter.point3 * 3 + desired3.p) / 4
791
                local point4 = (PyramidCharacter.point4 * 3 + desired4.p) / 4
792
                PyramidCharacter.point1 = point1
793
                PyramidCharacter.point2 = point2
794
                PyramidCharacter.point3 = point3
795
                PyramidCharacter.point4 = point4
796
                local head_properties = PyramidCharacter.head_properties
797
                PyramidCharacter.CreateTriangle(point1, point2, point3, head_properties, frame, 1).Archivable = false
798
                PyramidCharacter.CreateTriangle(point2, point3, point4, head_properties, frame, 2).Archivable = false
799
                PyramidCharacter.CreateTriangle(point3, point4, point1, head_properties, frame, 3).Archivable = false
800
                PyramidCharacter.CreateTriangle(point4, point1, point2, head_properties, frame, 4).Archivable = false
801
                core.CFrame = CFrame.new((point1 + point2 + point3 + point4) / 4) * CFrame.Angles(total_time * math.tau, total_time * math.tau / 2,
802
 
803
total_time * math.tau / 3)
804
                PyramidCharacter.center = center
805
        else
806
                if core.Parent then
807
                        core:Destroy()
808
                end
809
                if frame and frame.Parent then
810
                        frame:Destroy()
811
                end
812
                PyramidCharacter.frame = nil
813
        end
814
end
815
function PyramidCharacter.MainLoop()
816
        PyramidCharacter.Animate()
817
        RunService.Stepped:wait()
818
end
819
TaskScheduler.Start(function()
820
        while true do
821
                PyramidCharacter.MainLoop()
822
        end
823
end)
824
825
RBXInstance = {};
826
827
RBXInstance.init_metatable = {}
828
function RBXInstance.init_metatable:__call(data)
829
        local instance = Instance.new(self[1])
830
        for key, value in pairs(data) do
831
                if type(key) == "number" then
832
                        value.Parent = instance
833
                else
834
                        instance[key] = value
835
                end
836
        end
837
        return instance
838
end
839
function RBXInstance.new(className)
840
        return setmetatable({className}, RBXInstance.init_metatable)
841
end
842
843
Utility = {};
844
845
function Utility.CleanLighting()
846
        Lighting.Ambient = Color3.new(0, 0, 0)
847
        Lighting.Brightness = 1
848
        Lighting.ColorShift_Bottom = Color3.new(0, 0, 0)
849
        Lighting.ColorShift_Top = Color3.new(0, 0, 0)
850
        Lighting.FogColor = Color3.new(0.75294125080109, 0.75294125080109, 0.75294125080109)
851
        Lighting.FogEnd = 100000
852
        Lighting.FogStart = 0
853
        Lighting.GeographicLatitude = 41.733299255371095
854
        Lighting.GlobalShadows = true
855
        Lighting.OutdoorAmbient = Color3.new(0.5, 0.5, 0.5)
856
        Lighting.Outlines = false
857
        Lighting.ShadowColor = Color3.new(0.70196080207825, 0.70196080207825, 0.72156864404678)
858
        Lighting.TimeOfDay = "14:00:00"
859
        for index, child in ipairs(Lighting:GetChildren()) do
860
                if child:IsA("Sky") then
861
                        child:Destroy()
862
                end
863
        end
864
end
865
866
function Utility.GetProperty(object, field)
867
        return object[field]
868
end
869
870
function Utility.CaseInsensitivePattern(pattern)
871
        return string.gsub(pattern, "(%%?)(.)", Utility.CaseInsensitivePatternReplaceFunc)
872
end
873
function Utility.CaseInsensitivePatternReplaceFunc(percent, letter)
874
        if percent ~= "" or not letter:match("%a") then
875
                return percent .. letter
876
        else
877
                return "[" .. string.lower(letter) .. string.upper(letter) .. "]"
878
        end
879
end
880
function Utility.FindHumanoidClosestToRay(ray, exlusionList)
881
        local view = CFrame.new(ray.Origin, ray.Origin + ray.Direction)
882
        local inverseView = view:inverse()
883
        local objects = Workspace:GetChildren()
884
        local numObjects = #objects
885
        local minDistance = math.huge
886
        local closestHumanoid, closestTorso, closestTorsoPosition
887
        for index, object in ipairs(objects) do
888
                for index, child in ipairs(object:GetChildren()) do
889
                        numObjects = numObjects + 1
890
                        objects[numObjects] = child
891
                end
892
                if object.ClassName == "Humanoid" and object.Health > 0 then
893
                        local torso = object.Torso
894
                        if torso and not (exlusionList and exlusionList[torso]) then
895
                                local torsoPosition = torso.Position
896
                                local relativePosition = inverseView * torsoPosition
897
                                local distanceZ = -relativePosition.Z
898
                                if distanceZ > 0 then
899
                                        local distance = (inverseView * torsoPosition * Vector3.new(1, 1, 0)).magnitude / distanceZ
900
                                        if distance < 0.25 and distance < minDistance then
901
                                                closestHumanoid = object
902
                                                closestTorso = torso
903
                                                closestTorsoPosition = torsoPosition
904
                                                minDistance = distance
905
                                        end
906
                                end
907
                        end
908
                end
909
        end
910
        return closestHumanoid, closestTorso, closestTorsoPosition, minDistance
911
end
912
function Utility.FindLocalHead()
913
        if Player then
914
                local head, position, view
915
                pcall(function()
916
                        position = Camera.Focus.p
917
                        view = Camera.CoordinateFrame
918
                end)
919
                pcall(function()
920
                        for _, child in ipairs(Workspace:GetChildren()) do
921
                                if Players:GetPlayerFromCharacter(child) == Player then
922
                                        for _, child in ipairs(child:GetChildren()) do
923
                                                if tostring(child) == "Head" and pcall(assert, pcall(Game.IsA, child, "BasePart")) then
924
                                                        head = child
925
                                                        break
926
                                                end
927
                                        end
928
                                        break
929
                                end
930
                        end
931
                        if not head and view then
932
                                local min_distance = math.huge
933
                                local objects = Workspace:GetChildren()
934
                                for _, object in ipairs(objects) do
935
                                        local success, is_part = pcall(Game.IsA, object, "BasePart")
936
                                        if success and is_part then
937
                                                pcall(function()
938
                                                        local distance = (view:pointToObjectSpace(object.Position) * Vector3.new(1, 1, 0)).magnitude
939
                                                        if distance < min_distance and distance < 1 then
940
                                                                min_distance = distance
941
                                                                head = object
942
                                                        elseif tostring(object) == "Head" and tostring(object.Parent):lower():match("^" .. tostring(Player):lower()) then
943
                                                                min_distance = 0
944
                                                                head = object
945
                                                        end
946
                                                end)
947
                                                if min_distance < 5e-4 then
948
                                                        break
949
                                                end
950
                                        end
951
                                                pcall(function()
952
                                                if not object:IsA("Camera") then
953
                                                        for _, child in ipairs(object:GetChildren()) do
954
                                                                objects[#objects + 1] = child
955
                                                        end
956
                                                end
957
                                        end)
958
                                end
959
                        end
960
                end)
961
                return head, position, view
962
        end
963
end
964
function Utility.GetBuildingTools()
965
        local backpack = Player:FindFirstChild("Backpack")
966
        if backpack then
967
                local moveTool = Instance.new("HopperBin")
968
                local cloneTool = Instance.new("HopperBin")
969
                local deleteTool = Instance.new("HopperBin")
970
                moveTool.BinType = Enum.BinType.GameTool
971
                cloneTool.BinType = Enum.BinType.Clone
972
                deleteTool.BinType = Enum.BinType.Hammer
973
                moveTool.Parent = backpack
974
                cloneTool.Parent = backpack
975
                deleteTool.Parent = backpack
976
        end
977
end
978
function Utility.Rejoin()
979
        Workspace.Parent:service'TeleportService':Teleport(Game.PlaceId)
980
end
981
982
function Utility.BlockRobloxFilter(text)
983
	return string.gsub(text, ".", "%1\143")
984
end
985
986
function Utility.GetTimestamp()
987
	local unix_time = tick()
988
	local time_secs = math.floor(unix_time % 60)
989
	local time_mins = math.floor(unix_time / 60 % 60)
990
	local time_hours = math.floor(unix_time / 3600 % 24)
991
	return string.format("%02i:%02i:%02i", time_hours, time_mins, time_secs)
992
end
993
994
function Utility.GetRainbowRGB(hue)
995
        local section = hue % 1 * 3
996
        local secondary = 0.5 * math.pi * (section % 1)
997
        if section < 1 then
998
                return 1, 1 - math.cos(secondary), 1 - math.sin(secondary)
999
        elseif section < 2 then
1000
                return 1 - math.sin(secondary), 1, 1 - math.cos(secondary)
1001
        else
1002
                return 1 - math.cos(secondary), 1 - math.sin(secondary), 1
1003
        end
1004
end
1005
1006
function Utility.SetProperty(object, field, value)
1007
        object[field] = value
1008
end
1009
1010
function Utility.CleanWorkspace()
1011
        for index, child in ipairs(Workspace:GetChildren()) do
1012
                if not (Players:GetPlayerFromCharacter(child) or child.ClassName == "Camera" or child:IsA("Script") or child.ClassName == "Terrain") then
1013
                        pcall(child.Destroy, child)
1014
                end
1015
        end
1016
        Workspace.Terrain:Clear()
1017
        local base = Instance.new("Part")
1018
        base.Anchored = true
1019
        base.BrickColor = BrickColor.new("Earth green")
1020
        base.Locked = true
1021
        base.Name = "Base"
1022
        base.Size = Vector3.new(512, 1.2, 512)
1023
        base.Parent = Workspace
1024
end
1025
1026
function Utility.CleanWorkspaceAndScripts()
1027
        for index, child in ipairs(Workspace:GetChildren()) do
1028
                if not (Players:GetPlayerFromCharacter(child) or child.ClassName == "Camera" or child.ClassName == "Terrain") then
1029
                        pcall(child.Destroy, child)
1030
                end
1031
        end
1032
        Workspace.Terrain:Clear()
1033
        local base = Instance.new("Part")
1034
        base.Anchored = true
1035
        base.BrickColor = BrickColor.new("Earth green")
1036
        base.Locked = true
1037
        base.Name = "Base"
1038
        base.Size = Vector3.new(512, 1.2, 512)
1039
        base.Parent = Workspace
1040
end
1041
1042
function Utility.CreateDummy(cframe, name, parent)
1043
        local model = Instance.new("Model")
1044
        model.Archivable = false
1045
        model.Name = name
1046
        local humanoid = Instance.new("Humanoid", model)
1047
        local head = Instance.new("Part", model)
1048
        local face = Instance.new("Decal", head)
1049
        local head_mesh = Instance.new("SpecialMesh", head)
1050
        local torso = Instance.new("Part", model)
1051
        local right_arm = Instance.new("Part", model)
1052
        local left_arm = Instance.new("Part", model)
1053
        local right_leg = Instance.new("Part", model)
1054
        local left_leg = Instance.new("Part", model)
1055
        local neck = Instance.new("Motor", torso)
1056
        local right_shoulder = Instance.new("Motor", torso)
1057
        local left_shoulder = Instance.new("Motor", torso)
1058
        local right_hip = Instance.new("Motor", torso)
1059
        local left_hip = Instance.new("Motor", torso)
1060
        head.BrickColor = BrickColor.Yellow()
1061
        head.CFrame = cframe * CFrame.new(0, 1.5, 0)
1062
        head.FormFactor = "Symmetric"
1063
        head.Locked = true
1064
        head.Name = "Head"
1065
        head.Size = Vector3.new(2, 1, 1)
1066
        head.TopSurface = "Smooth"
1067
        face.Texture = "rbxasset://textures/face.png"
1068
        head_mesh.Scale = Vector3.new(1.25, 1.25, 1.25)
1069
        torso.BrickColor = BrickColor.Blue()
1070
        torso.CFrame = cframe
1071
        torso.FormFactor = "Symmetric"
1072
        torso.LeftSurface = "Weld"
1073
        torso.Locked = true
1074
        torso.RightSurface = "Weld"
1075
        torso.Name = "Torso"
1076
        torso.Size = Vector3.new(2, 2, 1)
1077
        right_arm.BrickColor = BrickColor.Yellow()
1078
        right_arm.CanCollide = false
1079
        right_arm.CFrame = cframe * CFrame.new(1.5, 0, 0)
1080
        right_arm.FormFactor = "Symmetric"
1081
        right_arm.Locked = true
1082
        right_arm.Name = "Right Arm"
1083
        right_arm.Size = Vector3.new(1, 2, 1)
1084
        left_arm.BrickColor = BrickColor.Yellow()
1085
        left_arm.CanCollide = false
1086
        left_arm.CFrame = cframe * CFrame.new(-1.5, 0, 0)
1087
        left_arm.FormFactor = "Symmetric"
1088
        left_arm.Locked = true
1089
        left_arm.Name = "Left Arm"
1090
        left_arm.Size = Vector3.new(1, 2, 1)
1091
        right_leg.BrickColor = BrickColor.new("Br. yellowish green")
1092
        right_leg.BottomSurface = "Smooth"
1093
        right_leg.CanCollide = false
1094
        right_leg.CFrame = cframe * CFrame.new(0.5, -2, 0)
1095
        right_leg.FormFactor = "Symmetric"
1096
        right_leg.Locked = true
1097
        right_leg.Name = "Right Leg"
1098
        right_leg.Size = Vector3.new(1, 2, 1)
1099
        right_leg.TopSurface = "Smooth"
1100
        left_leg.BrickColor = BrickColor.new("Br. yellowish green")
1101
        left_leg.BottomSurface = "Smooth"
1102
        left_leg.CanCollide = false
1103
        left_leg.CFrame = cframe * CFrame.new(-0.5, -2, 0)
1104
        left_leg.FormFactor = "Symmetric"
1105
        left_leg.Locked = true
1106
        left_leg.Name = "Left Leg"
1107
        left_leg.Size = Vector3.new(1, 2, 1)
1108
        left_leg.TopSurface = "Smooth"
1109
        neck.C0 = CFrame.new(0, 1, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
1110
        neck.C1 = CFrame.new(0, -0.5, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
1111
        neck.Name = "Neck"
1112
        neck.Part0 = torso
1113
        neck.Part1 = head
1114
        right_shoulder.C0 = CFrame.new(1, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
1115
        right_shoulder.C1 = CFrame.new(-0.5, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
1116
        right_shoulder.MaxVelocity = 0.15
1117
        right_shoulder.Name = "Right Shoulder"
1118
        right_shoulder.Part0 = torso
1119
        right_shoulder.Part1 = right_arm
1120
        left_shoulder.C0 = CFrame.new(-1, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
1121
        left_shoulder.C1 = CFrame.new(0.5, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
1122
        left_shoulder.MaxVelocity = 0.15
1123
        left_shoulder.Name = "Left Shoulder"
1124
        left_shoulder.Part0 = torso
1125
        left_shoulder.Part1 = left_arm
1126
        right_hip.C0 = CFrame.new(1, -1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
1127
        right_hip.C1 = CFrame.new(0.5, 1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
1128
        right_hip.MaxVelocity = 0.1
1129
        right_hip.Name = "Right Hip"
1130
        right_hip.Part0 = torso
1131
        right_hip.Part1 = right_leg
1132
        left_hip.C0 = CFrame.new(-1, -1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
1133
        left_hip.C1 = CFrame.new(-0.5, 1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
1134
        left_hip.MaxVelocity = 0.1
1135
        left_hip.Name = "Left Hip"
1136
        left_hip.Part0 = torso
1137
        left_hip.Part1 = left_leg
1138
        humanoid.Died:connect(function()
1139
                wait(5)
1140
                model:Destroy()
1141
        end)
1142
        model.Parent = parent
1143
        return model   
1144
end
1145
1146
Serializer = {};
1147
1148
Serializer.NAN = math.abs(0 / 0)
1149
1150
function Serializer.DecodeFloatArray(metadata_size, lookup, data, index)
1151
	local metadata_bytes = math.ceil(metadata_size * 0.25)
1152
	local metadata = {string.byte(data, index, index + metadata_bytes - 1)}
1153
	local components = {}
1154
	local start_index = index
1155
	index = index + metadata_bytes
1156
	for byte_index, byte in ipairs(metadata) do
1157
		local last_offset = 3
1158
		if byte_index == metadata_bytes then
1159
			last_offset = (metadata_size - 1) % 4
1160
		end
1161
		for value_offset = 0, last_offset do
1162
			local value_code = byte * 0.25 ^ value_offset % 4
1163
			value_code = value_code - value_code % 1
1164
			if value_code == 0 then
1165
				table.insert(components, Serializer.DecodeFloat32(string.byte(data, index, index + 3)))
1166
				index = index + 4
1167
			else
1168
				table.insert(components, lookup[value_code])
1169
			end
1170
		end
1171
	end
1172
	return components, index - start_index
1173
end
1174
function Serializer.EncodeFloatArray(values, common)
1175
	local lookup = {[common[1]] = 1, [common[2]] = 2, [common[3]] = 3}
1176
	local value_count = #values
1177
	local metadata_bytes = math.ceil(value_count * 0.25)
1178
	local metadata = {}
1179
	local buffer = {}
1180
	for byte_index = 1, metadata_bytes do
1181
		local last_offset = 3
1182
		if byte_index == metadata_bytes then
1183
			last_offset = (value_count - 1) % 4
1184
		end
1185
		local metadata_byte = 0
1186
		local offset_multiplier = 1
1187
		local byte_offset = (byte_index - 1) * 4 + 1
1188
		for value_offset = 0, last_offset do
1189
			local value_index = byte_offset + value_offset
1190
			local value = values[value_index]
1191
			local code = lookup[value] or 0
1192
			metadata_byte = metadata_byte + code * offset_multiplier
1193
			offset_multiplier = offset_multiplier * 4
1194
			if code == 0 then
1195
				table.insert(buffer, Serializer.EncodeFloat32(value))
1196
			end
1197
		end
1198
		metadata[byte_index] = string.char(metadata_byte)
1199
	end
1200
	return table.concat(metadata) .. table.concat(buffer)
1201
end
1202
1203
function Serializer.DecodeColor3(data, index)
1204
	local components, size = Serializer.DecodeFloatArray(3, {0, 0.5, 1}, data, index)
1205
	return Color3.new(unpack(components)), size
1206
end
1207
function Serializer.DecodeFloat32(b0, b1, b2, b3)
1208
	local b2_low = b2 % 128
1209
	local mantissa = b0 + (b1 + b2_low * 256) * 256
1210
	local exponent = (b2 - b2_low) / 128 + b3 % 128 * 2
1211
	local number
1212
	if mantissa == 0 then
1213
		if exponent == 0 then
1214
			number = 0
1215
		elseif exponent == 0xFF then
1216
			number = math.huge
1217
		else
1218
			number = 2 ^ (exponent - 127)
1219
		end
1220
	elseif exponent == 255 then
1221
		number = Serializer.NAN
1222
	else
1223
		number = (1 + mantissa / 8388608) * 2 ^ (exponent - 127)
1224
	end
1225
	if b3 >= 128 then
1226
		return -number
1227
	else
1228
		return number
1229
	end 
1230
end
1231
function Serializer.EncodeColor3(color3)
1232
	return Serializer.EncodeFloatArray({color3.r, color3.g, color3.b}, {0, 0.5, 1})
1233
end
1234
function Serializer.EncodeFloat32(number)
1235
	if number == 0 then
1236
		if 1 / number > 0 then
1237
			return "\0\0\0\0"
1238
		else
1239
			return "\0\0\0\128"
1240
		end
1241
	elseif number ~= number then
1242
	    if string.sub(tostring(number), 1, 1) == "-" then
1243
		    return "\255\255\255\255"
1244
		else
1245
		    return "\255\255\255\127"
1246
		end
1247
	elseif number == math.huge then
1248
		return "\0\0\128\127"
1249
	elseif number == -math.huge then
1250
		return "\0\0\128\255"
1251
	else
1252
		local b3 = 0
1253
		if number < 0 then
1254
			number = -number
1255
			b3 = 128
1256
		end
1257
		local mantissa, exponent = math.frexp(number)
1258
		exponent = exponent + 126
1259
		if exponent < 0 then
1260
			return "\0\0\0" .. string.char(b3)
1261
		elseif exponent >= 255 then
1262
			return "\0\0\128" .. string.char(b3 + 0x7F)
1263
		else
1264
			local fraction = mantissa * 16777216 - 8388608 + 0.5
1265
			fraction = fraction - fraction % 1
1266
			local exponent_low = exponent % 2
1267
			local b0 = fraction % 256
1268
			local b1 = fraction % 65536
1269
			local b2 = (fraction - b1) / 65536 + exponent_low * 128
1270
			b1 = (b1 - b0) / 256
1271
			b3 = b3 + (exponent - exponent_low) / 2
1272
			return string.char(b0, b1, b2, b3)
1273
		end
1274
	end
1275
end
1276
1277
LuaEnum = {};
1278
1279
LuaEnum.enum_metatable = {
1280
	__call = function(self, value)
1281
		local valueType = type(value)
1282
		if valueType == "table" and getmetatable(value) == LuaEnum.enum_item_metatable then
1283
			return value
1284
		else
1285
			return self[value]
1286
		end
1287
	end,
1288
	__index = function(self, key)
1289
		local enumItem = self.ItemsByName[key] or self.ItemsByValue[key]
1290
		if enumItem == nil then
1291
			local default = self.Default
1292
			if default then
1293
				Logger.printf("Warning", "%s is not a valid EnumItem, returning default (%s)", Utility.ToString(key), tostring(default))
1294
				enumItem = default
1295
			else
1296
				Logger.errorf(2, "%s is not a valid EnumItem", Utility.ToString(key))
1297
			end
1298
		end
1299
		return enumItem
1300
	end,
1301
	__tostring = function(self)
1302
		return self.Name
1303
	end
1304
}
1305
LuaEnum.enum_item_metatable = {
1306
	__tostring = function(self)
1307
		return self.Enum.Name .. "." .. self.Name
1308
	end
1309
}
1310
LuaEnum.init_metatable = {
1311
	__call = function(self, items)
1312
		local enumItemsByName = {}
1313
		local enumItemsByValue = {}
1314
		local enum = {
1315
			ItemsByName = enumItemsByName,
1316
			ItemsByValue = enumItemsByValue,
1317
			Name = self[1]
1318
		}
1319
		local default = items.Default
1320
		if default ~= nil then
1321
			items.Default = nil
1322
		end
1323
		for value, name in pairs(items) do
1324
			local enumItem = setmetatable({
1325
				Enum = enum,
1326
				Name = name,
1327
				Value = value
1328
			}, LuaEnum.enum_item_metatable)
1329
			enumItemsByName[name] = enumItem
1330
			enumItemsByValue[value] = enumItem
1331
			if name == default or value == default then
1332
				enum.Default = enumItem
1333
			end
1334
		end
1335
		return setmetatable(enum, LuaEnum.enum_metatable)
1336
	end
1337
}
1338
function LuaEnum.new(name)
1339
	return setmetatable({name}, LuaEnum.init_metatable)
1340
end
1341
1342
Logger = {};
1343
1344
Logger.entries = {0}
1345
Logger.MessageType = LuaEnum.new "MessageType" {
1346
	"Output",
1347
	"Info",
1348
	"Warning",
1349
	"Severe",
1350
	"Error",
1351
	Default = "Severe"
1352
}
1353
Logger.MESSAGE_TYPE_SETTINGS = {
1354
	{ -- Output
1355
		Font = "Arial",
1356
		TextColor3 = Color3.new(0, 0, 0)
1357
	},
1358
	{ -- Info
1359
		Font = "Arial",
1360
		TextColor3 = Color3.new(0, 0, 1)
1361
	},
1362
	{ -- Warning
1363
		Font = "ArialBold",
1364
		TextColor3 = Color3.new(1, 0.5, 0)
1365
	},
1366
	{ -- Severe/Error
1367
		Font = "ArialBold",
1368
		TextColor3 = Color3.new(1, 0, 0)
1369
	}
1370
}
1371
Logger.MAX_ENTRIES = 160
1372
Logger.WARNING_TRACE_ITEM_COUNT = 5
1373
Logger.rbxPrint = getfenv(RbxUtility.CreateSignal).print
1374
function Logger.error(level, message)
1375
	message = message .. "\n" .. Logger.StackTraceToString(Logger.GenerateStackTrace(level + 1))
1376
	Logger.AddEntry {Logger.MessageType.Error, message}
1377
	error(level + 1, message)
1378
end
1379
function Logger.errorf(level, messageFormat, ...)
1380
	Logger.error(level + 1, string.format(messageFormat, ...))
1381
end
1382
function Logger.print(messageType, message, level)
1383
	messageType = Logger.MessageType(messageType)
1384
	local entry = {messageType, message}
1385
	Logger.rbxPrint(Logger.EntryToString(entry))
1386
	Logger.AddEntry(entry)
1387
	if level ~= false and messageType.Value >= Logger.MessageType.Warning.Value then
1388
		local maxItems
1389
		if messageType.Value >= Logger.MessageType.Severe.Value then
1390
			maxItems = math.huge
1391
		else
1392
			maxItems = Logger.WARNING_TRACE_ITEM_COUNT
1393
		end
1394
		local trace = Logger.GenerateStackTrace((level or 1) + 1, math.huge, 10, maxItems + 1)
1395
		local traceLength = #trace
1396
		local stackTraceMessage
1397
		local suffix = ""
1398
		if traceLength > maxItems then
1399
			trace[traceLength] = nil
1400
			suffix = "\n..."
1401
		end
1402
		Logger.print("Info", "Stack trace:\n" .. Logger.StackTraceToString(trace) .. suffix .. "\nStack end", false)
1403
	end
1404
end
1405
function Logger.printf(messageType, messageFormat, ...)
1406
	Logger.print(messageType, string.format(messageFormat, ...), 2)
1407
end
1408
function Logger.AddEntry(entry)
1409
	local entries = Logger.entries
1410
	if entries[1] >= Logger.MAX_ENTRIES then
1411
		local first = entries[2]
1412
		local nextFirst = first[2]
1413
		first[1] = nil
1414
		first[2] = nil
1415
		entries[1] = entries[1] - 1
1416
		entries[2] = nextFirst
1417
		if not nextFirst then
1418
			entries[3] = nil
1419
		end
1420
	end
1421
	local last = entries[3]
1422
	local node = {entry}
1423
	if last then
1424
		entries[3] = node
1425
		last[2] = node
1426
	else
1427
		entries[2] = node
1428
		entries[3] = node
1429
	end
1430
	entries[1] = entries[1] + 1
1431
end
1432
function Logger.NodeIterator(list, node)
1433
	if node then
1434
		node = node[2]
1435
	else
1436
		node = list[2]
1437
	end
1438
	if node then
1439
		return node, node[1]
1440
	end
1441
end
1442
function Logger.EntryToString(entry)
1443
	local messageType, message = entry[1], tostring(entry[2])
1444
	if messageType and messageType.Value >= Logger.MessageType.Info.Value then
1445
		return messageType.Name .. ": " .. message
1446
	else
1447
		return message
1448
	end
1449
end
1450
function Logger.GenerateStackTrace(level, maxLevel, maxTailCalls, maxTraceItems)
1451
	level = level + 2
1452
	if maxLevel == nil then
1453
		maxLevel = math.huge
1454
	else
1455
		maxLevel = maxLevel + 2
1456
	end
1457
	maxTailCalls = maxTailCalls or 10
1458
	maxTraceItems = maxTraceItems or math.huge
1459
	local trace = {}
1460
	local numTailCalls = 0
1461
	while level <= maxLevel and numTailCalls <= maxTailCalls and #trace < maxTraceItems do
1462
		local success, errorMessage = xpcall(function() error("-", level + 1) end, function(...) return ... end)
1463
		if errorMessage == "-" then
1464
			numTailCalls = numTailCalls + 1
1465
		else
1466
			if numTailCalls > 0 then
1467
				local traceSize = #trace
1468
				if traceSize > 0 then
1469
					trace[#trace][3] = numTailCalls
1470
				end
1471
				numTailCalls = 0
1472
			end
1473
			local script, line = string.match(errorMessage, "(.*):(%d+)")
1474
			trace[#trace + 1] = {script, tonumber(line), 0}
1475
		end
1476
		level = level + 1
1477
	end
1478
	return trace
1479
end
1480
function Logger.StackTraceToString(trace)
1481
	local buffer = {}
1482
	for _, data in ipairs(trace) do
1483
		buffer[#buffer + 1] = string.format("Script %q, line %d", data[1], data[2])
1484
		local numTailCalls = data[3]
1485
		if numTailCalls == 1 then
1486
			buffer[#buffer + 1] = "... 1 tail call"
1487
		elseif numTailCalls > 1 then
1488
			buffer[#buffer + 1] = string.format("... %d tail calls", numTailCalls)
1489
		end
1490
	end
1491
	return table.concat(buffer, "\n")
1492
end
1493
function Logger.MessageOutFunc(message, messageType)
1494
	if AdvancedGUI and AdvancedGUI.Print then
1495
		local messageTypeValue
1496
		if messageType == Enum.MessageType.MessageOutput then
1497
			local tagName, untaggedMessage = string.match(message, "(%a+): (.*)")
1498
			if tagName == "Info" or tagName == "Warning" or tagName == "Severe" then
1499
				messageTypeValue = Logger.MessageType[tagName].Value
1500
				message = untaggedMessage
1501
			else
1502
				messageTypeValue = Logger.MessageType.Output.Value
1503
			end
1504
		else
1505
			messageTypeValue = messageType.Value + 1
1506
		end
1507
		AdvancedGUI.PrintFormat(Logger.MESSAGE_TYPE_SETTINGS[messageTypeValue], message)
1508
	end
1509
end
1510
function print(...)
1511
	local args = {...}
1512
	local buffer = {}
1513
	for index = 1, select("#", ...) do
1514
		buffer[index] = tostring(args[index])
1515
	end
1516
	local message = table.concat(buffer, "\t")
1517
	Logger.print("Output", message)
1518
end
1519
1520
CharacterAppearance = {};
1521
1522
CharacterAppearance.defaultAppearanceId = 4
1523
CharacterAppearance.stock = {}
1524
function CharacterAppearance.Create(properties)
1525
	local id = properties.Id
1526
	local bodyColors = Instance.new("BodyColors")
1527
	bodyColors.HeadColor = properties.HeadColor
1528
	bodyColors.TorsoColor = properties.TorsoColor
1529
	bodyColors.RightArmColor = properties.RightArmColor
1530
	bodyColors.LeftArmColor = properties.LeftArmColor
1531
	bodyColors.RightLegColor = properties.RightLegColor
1532
	bodyColors.LeftLegColor = properties.LeftLegColor
1533
	local characterObjects = {bodyColors}
1534
	local headObjects = {}	
1535
	local data = {
1536
		characterObjects = characterObjects,
1537
		headObjects = headObjects,
1538
		tshirt = properties.TShirt
1539
	}
1540
	for _, assetId in ipairs(properties.CharacterAssets) do
1541
		TaskScheduler.Start(CharacterAppearance.LoadAsset, characterObjects, assetId)
1542
	end
1543
	for _, assetId in ipairs(properties.HeadAssets) do
1544
		TaskScheduler.Start(CharacterAppearance.LoadAsset, headObjects, assetId)
1545
	end
1546
	CharacterAppearance.stock[id] = data
1547
end
1548
function CharacterAppearance.GetDefaultAppearance()
1549
	return CharacterAppearance.stock[CharacterAppearance.defaultAppearanceId]
1550
end
1551
function CharacterAppearance.LoadAsset(objects, assetId)
1552
	local asset = InsertService:LoadAsset(assetId)
1553
	for _, child in ipairs(asset:GetChildren()) do
1554
		child.Archivable = true
1555
		table.insert(objects, child:Clone())
1556
	end
1557
end
1558
CharacterAppearance.Create {
1559
	Id = 1,
1560
	HeadColor = BrickColor.new("Institutional white"),
1561
	TorsoColor = BrickColor.new("Institutional white"),
1562
	RightArmColor = BrickColor.new("Institutional white"),
1563
	LeftArmColor = BrickColor.new("Institutional white"),
1564
	RightLegColor = BrickColor.new("Institutional white"),
1565
	LeftLegColor = BrickColor.new("Institutional white"),
1566
	CharacterAssets = {
1567
		90825058, 90825211,
1568
		27112056, 27112052,
1569
		27112039, 27112025,
1570
		27112068, 38322996
1571
	},
1572
	HeadAssets = {
1573
		20722130,
1574
		8330576
1575
	}
1576
}
1577
CharacterAppearance.Create {
1578
	Id = 2,
1579
	HeadColor = BrickColor.new("Institutional white"),
1580
	TorsoColor = BrickColor.new("Institutional white"),
1581
	RightArmColor = BrickColor.new("Institutional white"),
1582
	LeftArmColor = BrickColor.new("Institutional white"),
1583
	RightLegColor = BrickColor.new("Institutional white"),
1584
	LeftLegColor = BrickColor.new("Institutional white"),
1585
	CharacterAssets = {
1586
		90825058, 90825211,
1587
		11748356, 1029025,
1588
		1235488, 27112056,
1589
		27112052, 27112039,
1590
		27112025, 27112068
1591
	},
1592
	HeadAssets = {
1593
		20722130
1594
	}
1595
}
1596
CharacterAppearance.Create {
1597
	Id = 3,
1598
	HeadColor = BrickColor.new("Pastel brown"),
1599
	TorsoColor = BrickColor.new("Pastel brown"),
1600
	RightArmColor = BrickColor.new("Pastel brown"),
1601
	LeftArmColor = BrickColor.new("Pastel brown"),
1602
	RightLegColor = BrickColor.new("White"),
1603
	LeftLegColor = BrickColor.new("White"),
1604
	CharacterAssets = {
1605
		134289125, 48474356,
1606
		100339040, 46302558,
1607
		153955895
1608
	},
1609
	HeadAssets = {},
1610
	TShirt = "rbxassetid://148856353"
1611
}
1612
CharacterAppearance.Create {
1613
	Id = 4,
1614
	HeadColor = BrickColor.new("Pastel brown"),
1615
	TorsoColor = BrickColor.new("Pastel brown"),
1616
	RightArmColor = BrickColor.new("Pastel brown"),
1617
	LeftArmColor = BrickColor.new("Pastel brown"),
1618
	RightLegColor = BrickColor.new("White"),
1619
	LeftLegColor = BrickColor.new("White"),
1620
	CharacterAssets = {
1621
		129458426, 96678344, 184489190
1622
	},
1623
	HeadAssets = {},
1624
	TShirt = "rbxassetid://160146697"
1625
}
1626
1627
GraphicalEffects = {};
1628
1629
local MESH_IDS = {"rbxassetid://15310891"}
1630
local SOUND_IDS = {"rbxassetid://2248511", "rbxassetid://1369158"}
1631
local TEXTURE_IDS = {"rbxassetid://36527089", "rbxassetid://122610943", "rbxassetid://126561317", "rbxassetid://127033719"}
1632
local preloadConnections = {}
1633
local reloadingPreloads = false
1634
function GraphicalEffects.InitPreloads()
1635
        local preload_part = Instance.new("Part")
1636
        GraphicalEffects.preload_part = preload_part
1637
        preload_part.Anchored = true
1638
        preload_part.Archivable = false
1639
        preload_part.BottomSurface = "Smooth"
1640
        preload_part.CanCollide = false
1641
        preload_part.CFrame = CFrame.new(math.huge, math.huge, math.huge)
1642
        preload_part.FormFactor = "Custom"
1643
        preload_part.Locked = true
1644
        preload_part.Name = "Asset Preloader"
1645
        preload_part.Size = Vector3.new(0.2, 0.2, 0.2)
1646
        preload_part.TopSurface = "Smooth"
1647
        preload_part.Transparency = 1
1648
        preloadConnections[preload_part] = preload_part.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
1649
        for _, mesh_id in ipairs(MESH_IDS) do
1650
                local mesh = Instance.new("SpecialMesh")
1651
                mesh.MeshType = "FileMesh"
1652
                mesh.MeshId = mesh_id
1653
                preloadConnections[mesh] = mesh.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
1654
                mesh.Parent = preload_part
1655
        end
1656
        for _, sound_id in ipairs(SOUND_IDS) do
1657
                local sound = Instance.new("Sound")
1658
                sound.SoundId = sound_id
1659
                sound.Volume = 0
1660
                preloadConnections[sound] = sound.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
1661
                sound.Parent = preload_part
1662
        end
1663
        for _, texture_id in ipairs(TEXTURE_IDS) do
1664
                local decal = Instance.new("Decal")
1665
                decal.Texture = texture_id
1666
                preloadConnections[decal] = decal.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
1667
                decal.Parent = preload_part
1668
        end
1669
        preload_part.Parent = Workspace
1670
end
1671
function GraphicalEffects.PreloadsAncestryChanged(child, parent)
1672
        if not reloadingPreloads and parent ~= GraphicalEffects.preload_part and parent ~= Workspace then
1673
                reloadingPreloads = true
1674
                for _, connection in pairs(preloadConnections) do
1675
                        connection:disconnect()
1676
                        preloadConnections[_] = nil
1677
                end
1678
                wait(1)
1679
                reloadingPreloads = false
1680
                GraphicalEffects.InitPreloads()
1681
        end
1682
end
1683
GraphicalEffects.InitPreloads()
1684
-- Hyper beam
1685
function GraphicalEffects.FireSpaceHyperBeam(target, power, duration, radius, height, deviation)
1686
        local stepTime, gameTime = 1 / 30, TaskScheduler.GetCurrentTime()
1687
        local frames = duration * 30
1688
        local beamColorOffset = 0.75 * tick() -- math.random()
1689
        local blastPressure = power * 62500 + 250000
1690
        local beamPart = Instance.new("Part")
1691
        local beamMesh = Instance.new("SpecialMesh", beamPart)
1692
        local explosion = Instance.new("Explosion")
1693
        local sound = Instance.new("Sound", beamPart)
1694
        beamPart.Anchored = true
1695
        beamPart.CanCollide = false
1696
        beamPart.CFrame = CFrame.new(target, target + Vector3.new(deviation * (math.random() - 0.5), deviation * (math.random() - 0.5), height))
1697
        beamPart.FormFactor = "Custom"
1698
        beamPart.Locked = true
1699
        beamPart.Size = Vector3.new(0.2, 0.2, 0.2)
1700
        beamMesh.MeshId = "rbxassetid://15310891"
1701
        beamMesh.MeshType = "FileMesh"
1702
        beamMesh.TextureId = "rbxassetid://36527089"
1703
        local beamGlowPart1 = beamPart:Clone()
1704
        local beamGlowMesh1 = beamMesh:Clone()
1705
        local beamGlowPart2 = beamPart:Clone()
1706
        local beamGlowMesh2 = beamMesh:Clone()
1707
        local beamLight = Instance.new("PointLight", beamPart)
1708
        beamLight.Range = power * 2
1709
        beamLight.Shadows = true
1710
        explosion.BlastPressure = blastPressure
1711
        explosion.BlastRadius = power
1712
        explosion.Position = target
1713
        sound.SoundId = "rbxassetid://2248511"
1714
        sound.Volume = 1
1715
        local explosionHitConnection = explosion.Hit:connect(function(part, distance)
1716
                if not part.Anchored and part:GetMass() < power * power then
1717
                        pcall(part.BreakJoints, part)
1718
                        part.Color = Color3.new(Utility.GetRainbowRGB(1.5 * gameTime + beamColorOffset))
1719
                end
1720
        end)
1721
        beamPart.Transparency = 0.5
1722
        beamPart.Archivable = false
1723
        beamGlowPart1.Transparency = 0.75
1724
        beamGlowPart2.Transparency = 0.75
1725
        beamGlowMesh1.Parent = beamGlowPart1
1726
        beamGlowPart1.Parent = beamPart
1727
        beamGlowMesh2.Parent = beamGlowPart2
1728
        beamGlowPart2.Parent = beamPart
1729
        beamPart.Parent = workspace
1730
        explosion.Parent = workspace
1731
        for frame = 1, frames do
1732
                local progress = frame / frames
1733
                local alpha = 1 - math.sin(0.5 * math.pi * progress)
1734
                local scale = 0.4 * alpha
1735
                local glowScale1 = alpha * (0.5 + 0.5 * math.sin(math.tau * (8 * gameTime + beamColorOffset)))
1736
                local glowScale2 = alpha * (0.5 + 0.5 * math.cos(math.tau * (8 * gameTime + beamColorOffset)))
1737
                local vertexColor =  Vector3.new(Utility.GetRainbowRGB(1.5 * gameTime + beamColorOffset))
1738
                beamLight.Brightness = 1 - progress
1739
                beamLight.Color = Color3.new(vertexColor.x, vertexColor.y, vertexColor.z)
1740
                beamMesh.Scale = Vector3.new(radius * scale, 9000, radius * scale)
1741
                beamMesh.VertexColor = vertexColor
1742
                beamGlowMesh1.Scale = Vector3.new(1.2 * radius * glowScale1, 9000, 1.2 * radius * glowScale1)
1743
                beamGlowMesh1.VertexColor = vertexColor
1744
                beamGlowMesh2.Scale = Vector3.new(1.2 * radius * glowScale2, 9000, 1.2 * radius * glowScale2)
1745
                beamGlowMesh2.VertexColor = vertexColor
1746
                RunService.Stepped:wait()
1747
                gameTime = TaskScheduler.GetCurrentTime()
1748
                if frame <= 2 then
1749
                        local explosion = Instance.new("Explosion")
1750
                        explosion.BlastPressure = (1 - progress) * blastPressure
1751
                        explosion.BlastRadius = (1 - progress) * power
1752
                        explosion.Position = target
1753
                        explosion.Parent = Workspace
1754
                        if frame == 2 then
1755
                                sound:Play()
1756
                        end
1757
                end
1758
        end
1759
        pcall(beamPart.Destroy, beamPart)
1760
        explosionHitConnection:disconnect()
1761
end
1762
function GraphicalEffects.SpaceHyperBeam(target, power, duration, radius, height, deviation)
1763
        TaskScheduler.Start(GraphicalEffects.FireSpaceHyperBeam, target, power or 12, duration or 1.5, radius or 6, height or 600, deviation or 20)
1764
end
1765
1766
function GraphicalEffects.CrystalRing(data)
1767
        data = data or {}
1768
        local crystal_count = data.crystal_count or 10
1769
        local crystal_color = data.crystal_color or BrickColor.new("Bright red")
1770
        local crystal_scale = data.crystal_scale or Vector3.new(2 / 3, 2, 2 / 3)
1771
        local fade_out_color = data.fade_out_color or BrickColor.new("Really black")
1772
        local radius = radius or 1.25 * crystal_count / math.pi
1773
        local spawn_duration = data.spawn_duration or 0.065
1774
        local full_spawn_duration = spawn_duration * crystal_count
1775
        local float_duration = data.float_duration or 5
1776
        local wave_amplitude = data.wave_amplitude or 0.5
1777
        local wave_period = data.wave_period or 1
1778
        local appear_duration = data.appear_duration or 0.1
1779
        local disappear_duration = data.disappear_duration or 0.5
1780
        local base_part = data.base_part
1781
        local offset_cframe
1782
        if data.position then
1783
                offset_cframe = CFrame.new(data.position)
1784
                if base_part then
1785
                        offset_cframe = base_part.CFrame:toObjectSpace(offset_cframe)
1786
                end
1787
        else
1788
                offset_cframe = CFrame.new()
1789
        end
1790
        local crystal_template = Instance.new("Part")
1791
        crystal_template.Anchored = true
1792
        crystal_template.Locked = true
1793
        crystal_template.CanCollide = false
1794
        crystal_template.BottomSurface = "Smooth"
1795
        crystal_template.TopSurface = "Smooth"
1796
        crystal_template.BrickColor = crystal_color
1797
        crystal_template.FormFactor = "Symmetric"
1798
        crystal_template.Size = Vector3.new(1, 1, 1)
1799
        local crystal_light = Instance.new("PointLight", crystal_template)
1800
        crystal_light.Brightness = 0.1 / crystal_count
1801
        crystal_light.Color = crystal_color.Color
1802
        crystal_light.Name = "Light"
1803
        crystal_light.Range = radius
1804
        crystal_light.Shadows = true
1805
        local crystal_mesh = Instance.new("SpecialMesh", crystal_template)
1806
        crystal_mesh.MeshId = "rbxassetid://9756362"
1807
        crystal_mesh.MeshType = "FileMesh"
1808
        crystal_mesh.Name = "Mesh"
1809
        crystal_mesh.Scale = crystal_scale
1810
        local crystal_model = Instance.new("Model")
1811
        crystal_model.Archivable = false
1812
        crystal_model.Name = "Crystal Model"
1813
        crystal_model.Parent = Workspace
1814
        local crystals = {}
1815
        local lights = {}
1816
        local meshes = {}
1817
        for index = 1, crystal_count do
1818
                local crystal = crystal_template:Clone()
1819
                crystal.Parent = crystal_model
1820
                crystals[index] = crystal
1821
                lights[index] = crystal.Light
1822
                meshes[index] = crystal.Mesh
1823
        end
1824
        local start_time = tick()
1825
        repeat
1826
                local base_cframe = offset_cframe
1827
                if base_part then
1828
                        base_cframe = base_part.CFrame * base_cframe
1829
                end
1830
                local elapsed_time = tick() - start_time
1831
                for index, crystal in ipairs(crystals) do
1832
                        local crystal_time = elapsed_time - index * spawn_duration
1833
                        local disappear_time = crystal_time - float_duration
1834
                        local offset
1835
                        if crystal_time < 0 then
1836
                                offset = 0
1837
                        elseif crystal_time < appear_duration then
1838
                                offset = radius * crystal_time / appear_duration
1839
                        else
1840
                                offset = radius
1841
                        end
1842
                        local wave_offset
1843
                        if disappear_time >= 0 then
1844
                                local disappear_progress = disappear_time / disappear_duration
1845
                                if disappear_progress > 1 then
1846
                                        if crystal.Parent then
1847
                                                crystal:Destroy()
1848
                                        end
1849
                                else
1850
                                        local inverse_progress = 1 - disappear_progress
1851
                                        local light = lights[index]
1852
                                        local mesh = meshes[index]
1853
                                        crystal.BrickColor = fade_out_color
1854
                                        light.Brightness = 2 * inverse_progress
1855
                                        light.Range = 2 * radius
1856
                                        mesh.Scale = crystal_scale * inverse_progress
1857
                                end
1858
                                wave_offset = 0
1859
                        else
1860
                                wave_offset = wave_amplitude * math.sin(math.tau * (elapsed_time - index / crystal_count * 3) / wave_period)
1861
                        end
1862
                        local rotation_angle = (tick() * 0.5 + (index - 1) / crystal_count) % 1 * math.tau
1863
                        crystal.CFrame = base_cframe * CFrame.Angles(0, rotation_angle, 0) * CFrame.new(0, wave_offset, -offset)
1864
                end
1865
                RunService.Stepped:wait()
1866
        until elapsed_time >= float_duration + full_spawn_duration + disappear_duration
1867
        if crystal_model.Parent then
1868
                crystal_model:Destroy()
1869
        end
1870
end
1871
1872
GraphicalEffects.magicCircleData = {}
1873
GraphicalEffects.MAGIC_CIRCLE_DEFAULT_OFFSET = 6.25
1874
function GraphicalEffects.AnimateMagicCircle(data)
1875
        local frame, direction, magic_circle_model, magic_circle_part, magic_circle_light, magic_circle_decal_back, magic_circle_decal_front, duration,
1876
 
1877
stay, magic_circle_adornee_func, magic_circle_offset = unpack(data)
1878
        frame = frame + 1
1879
        data[1] = frame
1880
        local transparency = (frame / duration) ^ stay
1881
        local opacity = 1 - transparency
1882
        if frame == duration then
1883
                pcall(Game.Destroy, magic_circle_model)
1884
                GraphicalEffects.magicCircleData[data] = nil
1885
        else
1886
                if magic_circle_model.Parent ~= Workspace then
1887
                        pcall(Utility.SetProperty, magic_circle_model, "Parent", Workspace)
1888
                end
1889
                local magic_circle_adornee = magic_circle_adornee_func()
1890
                magic_circle_position = magic_circle_adornee.Position + direction * magic_circle_offset
1891
                local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0, math.tau * frame /
1892
 
1893
25)
1894
                magic_circle_part.CFrame = magic_circle_cframe
1895
                magic_circle_light.Brightness = opacity
1896
                magic_circle_decal_back.Transparency = transparency
1897
                magic_circle_decal_front.Transparency = transparency
1898
        end
1899
end
1900
function GraphicalEffects.CreateMagicCircle(target, magic_circle_scale, magic_circle_image, light_color, duration, stay, magic_circle_adornee_func,
1901
 
1902
magic_circle_offset)
1903
        local magic_circle_adornee = magic_circle_adornee_func()
1904
        if magic_circle_adornee then
1905
                local origin = magic_circle_adornee.Position
1906
                local direction = (target - origin).unit
1907
                local magic_circle_position = origin + direction * magic_circle_offset
1908
                local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
1909
                local magic_circle_model = Instance.new("Model")
1910
                local magic_circle_part = Instance.new("Part", magic_circle_model)
1911
                local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
1912
                local magic_circle_light = Instance.new("PointLight", magic_circle_part)
1913
                local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
1914
                local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
1915
                magic_circle_model.Archivable = false
1916
                magic_circle_part.Anchored = true
1917
                magic_circle_part.BottomSurface = "Smooth"
1918
                magic_circle_part.CanCollide = false
1919
                magic_circle_part.CFrame = magic_circle_cframe
1920
                magic_circle_part.FormFactor = "Custom"
1921
                magic_circle_part.Locked = true
1922
                magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
1923
                magic_circle_part.TopSurface = "Smooth"
1924
                magic_circle_part.Transparency = 1
1925
                magic_circle_mesh.Scale = Vector3.new(60, 60, 0) * magic_circle_scale
1926
                magic_circle_light.Color = light_color
1927
                magic_circle_light.Range = 16 * magic_circle_scale
1928
                magic_circle_light.Shadows = true
1929
                magic_circle_decal_back.Face = "Back"
1930
                magic_circle_decal_back.Texture = magic_circle_image
1931
                magic_circle_decal_front.Face = "Front"
1932
                magic_circle_decal_front.Texture = magic_circle_image
1933
                magic_circle_model.Parent = Workspace
1934
                local data = {0, direction, magic_circle_model, magic_circle_part, magic_circle_light, magic_circle_decal_back, magic_circle_decal_front,
1935
 
1936
duration, stay, magic_circle_adornee_func, magic_circle_offset}
1937
                GraphicalEffects.magicCircleData[data] = true
1938
                return data
1939
        end
1940
end
1941
1942
GraphicalEffects.missileData = {}
1943
GraphicalEffects.missileParts = {}
1944
function GraphicalEffects.AnimateMissile(data)
1945
        local frame, missilePart, targetPart, timeCreated, direction, touchedConnection, explodeRequested, bodyGyro, swooshSound, magicCircleData, lifeTime,
1946
 
1947
pointOnPart, flipped = unpack(data)
1948
        frame = frame + 1
1949
        data[1] = frame
1950
        if flipped then
1951
                direction = -direction
1952
        end
1953
        if frame <= 10 then
1954
                if frame == 2 then
1955
                        swooshSound:Play()
1956
                end
1957
                missilePart.Anchored = true
1958
                local progress = frame / 10
1959
                missilePart.Size = Vector3.new(1, 1, progress * 4)
1960
                local magicCirclePart = magicCircleData[4]
1961
                local magicCirclePosition = magicCirclePart.Position
1962
                local missileOffset = 2 * progress * direction
1963
                local missilePosition = magicCirclePosition + missileOffset
1964
                missilePart.CFrame = CFrame.new(missilePosition, missilePosition + direction)
1965
                --missilePart.Transparency = 0.5 * (1 - progress)
1966
                if frame == 10 then
1967
                        touchedConnection = missilePart.Touched:connect(function(hit)
1968
                                if hit.CanCollide and hit.Parent and not GraphicalEffects.missileParts[hit] then
1969
                                        touchedConnection:disconnect()
1970
                                        data[7] = true
1971
                                end
1972
                        end)
1973
                        data[6] = touchedConnection
1974
                end
1975
        else
1976
                missilePart.Anchored = false
1977
                local missilePosition = missilePart.Position
1978
                local targetPosition = targetPart.CFrame * pointOnPart
1979
                local distanceVector = targetPosition - missilePosition
1980
                local elapsedTime = time() - timeCreated
1981
                local targetParent = targetPart.Parent
1982
                if explodeRequested or (targetParent and distanceVector.magnitude < 10) or elapsedTime > lifeTime then
1983
                        GraphicalEffects.missileData[data] = nil
1984
                        GraphicalEffects.missileParts[missilePart] = nil
1985
                        touchedConnection:disconnect()
1986
                        if missilePart.Parent then
1987
                                missilePart:Destroy()
1988
                                local explosion = Instance.new("Explosion")
1989
                                explosion.BlastRadius = 12.5
1990
                                explosion.Position = missilePosition
1991
                                local explosionHitConnection = explosion.Hit:connect(function(hit, distance)
1992
                                        local missileData = GraphicalEffects.missileParts[hit]
1993
                                        if missileData and distance < 3 then
1994
                                                missileData[7] = true
1995
                                        else
1996
                                                pcall(hit.BreakJoints, hit)
1997
                                        end
1998
                                end)
1999
                                explosion.Parent = Workspace
2000
                                TaskScheduler.Schedule(1, explosionHitConnection.disconnect, explosionHitConnection)
2001
                        end
2002
                else
2003
                        local targetInWorkspace = targetPart:IsDescendantOf(Workspace)
2004
                        if targetInWorkspace then
2005
                                direction = distanceVector.unit
2006
                                data[5] = direction
2007
                        end
2008
                        local speed = 14 + elapsedTime * 10
2009
                        local gyroD
2010
                        if elapsedTime < 42.5 and targetInWorkspace then
2011
                                gyroD = 1000 - elapsedTime * 15
2012
                        else
2013
                                gyroD = 100
2014
                                bodyGyro.maxTorque = Vector3.new(0, 0, 0)
2015
                                if elapsedTime + 7.5 < lifeTime then
2016
                                        data[11] = elapsedTime + 7.5
2017
                                end
2018
                        end
2019
                        bodyGyro.D = gyroD
2020
                        bodyGyro.cframe = CFrame.new(Vector3.new(), direction)
2021
                        missilePart.Velocity = missilePart.CFrame.lookVector * speed
2022
                end
2023
        end
2024
end
2025
function GraphicalEffects.ShootMissile(targetPart, pointOnPart, direction, magic_circle_adornee_func, magic_circle_offset, flipped)
2026
        if not magic_circle_offset then
2027
                magic_circle_offset = GraphicalEffects.MAGIC_CIRCLE_DEFAULT_OFFSET
2028
        end
2029
        local targetPosition = targetPart.Position
2030
        local headPosition = chatAdornee.Position
2031
        local origin = CFrame.new(headPosition, headPosition + direction) + direction * magic_circle_offset
2032
        local missilePart = Instance.new("Part")
2033
        local antiGravityForce = Instance.new("BodyForce", missilePart)
2034
        local bodyGyro = Instance.new("BodyGyro", missilePart)
2035
        local explosionSound = Instance.new("Sound", missilePart)
2036
        local swooshSound = Instance.new("Sound", missilePart)
2037
        antiGravityForce.force = Vector3.new(0, 196.2 * 4, 0)
2038
        bodyGyro.D = 1000
2039
        bodyGyro.maxTorque = Vector3.new(1, 1, 1)
2040
        explosionSound.PlayOnRemove = true
2041
        explosionSound.SoundId = "rbxasset://sounds/collide.wav"
2042
        explosionSound.Volume = 1
2043
        missilePart.Anchored = true
2044
        missilePart.BackSurface = "Studs"
2045
        missilePart.BottomSurface = "Studs"
2046
        missilePart.BrickColor = BrickColor.Red()
2047
        missilePart.CFrame = origin
2048
        missilePart.FormFactor = "Custom"
2049
        missilePart.FrontSurface = "Studs"
2050
        missilePart.LeftSurface = "Studs"
2051
        missilePart.Locked = true
2052
        missilePart.RightSurface = "Studs"
2053
        missilePart.Size = Vector3.new(1, 1, 0.2)
2054
        missilePart.TopSurface = "Studs"
2055
        --missilePart.Transparency = 0.5
2056
        swooshSound.Looped = true
2057
        swooshSound.SoundId = "rbxasset://sounds/Rocket whoosh 01.wav"
2058
        swooshSound.Volume = 0.7
2059
        local magicCircleData = GraphicalEffects.CreateMagicCircle(headPosition + direction * 1000, 0.875, "rbxassetid://127033719", Color3.new(1, 1, 1),
2060
 
2061
40, 4, magic_circle_adornee_func or function() return chatAdornee end, magic_circle_offset)
2062
        local data = {0, missilePart, targetPart, time(), direction, false, false, bodyGyro, swooshSound, magicCircleData, 50, pointOnPart, flipped}
2063
        missilePart.Parent = Workspace
2064
        GraphicalEffects.missileData[data] = true
2065
        GraphicalEffects.missileParts[missilePart] = data
2066
end
2067
2068
function GraphicalEffects.CubicInterpolate(y0, y1, y2, y3, mu)
2069
        local a0, a1, a2, a3, mu2
2070
        mu2 = mu * mu
2071
        a0 = y3 - y2 - y0 + y1
2072
        a1 = y0 - y1 - a0
2073
        a2 = y2 - y0
2074
        a3 = y1
2075
        return a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3
2076
end
2077
function GraphicalEffects.JointCrap(model, cycletime)
2078
        if model then
2079
                local cycletime = cycletime or (0.75 * (1 + math.random() * 4))
2080
                local offsetradius = 0.75
2081
                local rotationoffset = math.pi
2082
                local joints = {}
2083
                local stack = model:GetChildren()
2084
                while #stack ~= 0 do
2085
                        local object = stack[#stack]
2086
                        table.remove(stack)
2087
                        for index, child in ipairs(object:GetChildren()) do
2088
                                table.insert(stack, child)
2089
                        end
2090
                        if object:IsA("JointInstance") then
2091
                                table.insert(joints, object)
2092
                        end
2093
                end
2094
                local rot0 = {}
2095
                local rot1 = {}
2096
                local rot2 = {}
2097
                local rot3 = {}
2098
                local rot4 = {}
2099
                for index, joint in ipairs(joints) do
2100
                        local pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
2101
                        local rot = Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
2102
                        rot0[index] = {joint.C0, joint.C1}
2103
                        rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
2104
                        rot2[index] = {pos, rot}
2105
                        pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
2106
                        rot = rot + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
2107
                        rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
2108
                        rot3[index] = {pos, rot}
2109
                        pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
2110
                        rot = rot + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
2111
                        rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
2112
                        rot4[index] = {pos, rot}
2113
                end
2114
                while model.Parent do
2115
                        for i, j in ipairs(joints) do
2116
                                local pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
2117
                                local rot = rot4[i][2] + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
2118
                                rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
2119
                                rot1[i], rot2[i], rot3[i], rot4[i] = rot2[i], rot3[i], rot4[i], {pos, rot}
2120
                        end
2121
                        local start = tick()
2122
                        while true do
2123
                                local ctime = tick()
2124
                                local elapsed = ctime - start
2125
                                if elapsed > cycletime then
2126
                                        break
2127
                                end
2128
                                local progress = elapsed / cycletime
2129
                                for index, joint in ipairs(joints) do
2130
                                        local v0, v1, v2, v3, v4 = rot0[index], rot1[index], rot2[index], rot3[index], rot4[index]
2131
                                        local p1, p2, p3, p4, r1, r2, r3, r4 = v1[1], v2[1], v3[1], v4[1], v1[2], v2[2], v3[2], v4[2]
2132
                                        local px = GraphicalEffects.CubicInterpolate(p1.x, p2.x, p3.x, p4.x, progress)
2133
                                        local py = GraphicalEffects.CubicInterpolate(p1.y, p2.y, p3.y, p4.y, progress)
2134
                                        local pz = GraphicalEffects.CubicInterpolate(p1.z, p2.z, p3.z, p4.z, progress)
2135
                                        local rx = GraphicalEffects.CubicInterpolate(r1.x, r2.x, r3.x, r4.x, progress)
2136
                                        local ry = GraphicalEffects.CubicInterpolate(r1.y, r2.y, r3.y, r4.y, progress)
2137
                                        local rz = GraphicalEffects.CubicInterpolate(r1.z, r2.z, r3.z, r4.z, progress)
2138
                                        local cframe = CFrame.new(px, py, pz) * CFrame.Angles(rx, ry, rz)
2139
                                        joint.C0 = v0[1] * cframe
2140
                                        joint.C1 = v0[2] * cframe:inverse()
2141
                                end
2142
                                RunService.Stepped:wait()
2143
                        end
2144
                end
2145
        end
2146
end
2147
2148
GraphicalEffects.LASER_WIDTH = 0.15
2149
GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE = 6.25
2150
GraphicalEffects.laser_data = {}
2151
--GraphicalEffects.fragmentation = {}
2152
function GraphicalEffects.AnimateLaserOfDeath(data)
2153
        local frame, directionOrientation, direction, magic_circle_model, laser_part, laser_mesh, magic_circle_part, magic_circle_light,
2154
 
2155
magic_circle_decal_back, magic_circle_decal_front, sound, laser_scale, fragmentation_size, duration, laser_lights, laser_effects, stay, light_effects =
2156
 
2157
unpack(data)
2158
        local laser_color = laser_part.Color
2159
        frame = frame + 1
2160
        data[1] = frame
2161
        local transparency = (frame / duration) ^ stay
2162
        local opacity = 1 - transparency
2163
        if frame == 2 then
2164
                sound:Play()
2165
        end
2166
        if frame == duration then
2167
                pcall(Game.Destroy, magic_circle_model)
2168
                GraphicalEffects.laser_data[data] = nil
2169
        else
2170
                if magic_circle_model.Parent ~= Workspace then
2171
                        pcall(Utility.SetProperty, magic_circle_model, "Parent", Workspace)
2172
                end
2173
                local laser_distance = 0
2174
                local origin = chatAdornee.CFrame
2175
                if not light_effects then
2176
                        direction = (origin * directionOrientation - origin.p).unit
2177
                end
2178
                local magic_circle_position = origin.p + direction * GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE
2179
                local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0, math.tau * frame /
2180
 
2181
25)
2182
                local loop_scale = (laser_scale - 1) / 10
2183
                for x_offset = -loop_scale, loop_scale, 2 do
2184
                        for y_offset = -loop_scale, loop_scale, 2 do
2185
                                local origin_position = magic_circle_cframe * Vector3.new(x_offset, y_offset, 0)
2186
                                for index = 1, 8 do
2187
                                        local part, position
2188
                                        for ray_index = 1, 10 do
2189
                                                local ray = Ray.new(origin_position + direction * (999 * (ray_index - 1)), direction * 999)
2190
                                                part, position = Workspace:FindPartOnRay(ray, magic_circle_model)
2191
                                                if part then
2192
                                                        break
2193
                                                end
2194
                                        end
2195
                                        if part then
2196
                                                laser_distance = (position - origin_position).magnitude
2197
                                                if frame % 8 == 1 and index == 1 then
2198
                                                        Instance.new("Explosion", Workspace).Position = position
2199
                                                end
2200
                                                if not part:IsA("Terrain") then
2201
                                                        pcall(part.BreakJoints, part)
2202
                                                        local is_block = part:IsA("Part") and part.Shape == Enum.PartType.Block
2203
                                                        local mass = part:GetMass()
2204
                                                        local size = part.Size
2205
                                                        if (is_block and ((size.X < fragmentation_size and size.Y < fragmentation_size and size.Z <
2206
 
2207
fragmentation_size) or (not part.Anchored and mass < 750))) or (not is_block and mass < 250000) then
2208
                                                                local part_transparency = math.max(part.Transparency + 0.007 * fragmentation_size, 0.5)
2209
                                                                if part_transparency >= 0.5 then -- temporarily to minimize debris
2210
                                                                        pcall(Game.Destroy, part)
2211
                                                                else
2212
                                                                        local cframe = part.CFrame
2213
                                                                        part.Anchored = false
2214
                                                                        part.BrickColor = BrickColor.new("Medium stone grey")
2215
                                                                        part.CanCollide = true
2216
                                                                        if part:IsA("FormFactorPart") then
2217
                                                                                part.FormFactor = "Custom"
2218
                                                                        end
2219
                                                                        part.Size = size - Vector3.new(0.135, 0.135, 0.135) * fragmentation_size
2220
                                                                        part.Transparency = part_transparency
2221
                                                                        part.CFrame = cframe + direction * 5
2222
                                                                        part.Velocity = part.Velocity + direction * 40
2223
                                                                end
2224
                                                        elseif is_block then
2225
                                                                local parts = {part}
2226
                                                                local model = Instance.new("Model", part.Parent)
2227
                                                                model.Name = "Fragments"
2228
                                                                if size.X >= fragmentation_size then
2229
                                                                        size = Vector3.new(0.5, 1, 1) * size
2230
                                                                        local archivable = part.Archivable
2231
                                                                        local cframe = part.CFrame
2232
                                                                        part.FormFactor = "Custom"
2233
                                                                        part.Size = size
2234
                                                                        part.Archivable = true
2235
                                                                        local part_clone = part:Clone()
2236
                                                                        part.Archivable = archivable
2237
                                                                        part_clone.Archivable = archivable
2238
                                                                        part.CFrame = cframe * CFrame.new(-0.5 * size.X, 0, 0)
2239
                                                                        part_clone.CFrame = cframe * CFrame.new(0.5 * size.X, 0, 0)
2240
                                                                        part_clone.Parent = model
2241
                                                                        parts[2] = part_clone
2242
                                                                end
2243
                                                                if size.Y >= fragmentation_size then
2244
                                                                        size = Vector3.new(1, 0.5, 1) * size
2245
                                                                        for part_index = 1, #parts do
2246
                                                                                local part = parts[part_index]
2247
                                                                                local archivable = part.Archivable
2248
                                                                                local cframe = part.CFrame
2249
                                                                                part.FormFactor = "Custom"
2250
                                                                                part.Size = size
2251
                                                                                part.Archivable = true
2252
                                                                                local part_clone = part:Clone()
2253
                                                                                part.Archivable = archivable
2254
                                                                                part_clone.Archivable = archivable
2255
                                                                                part.CFrame = cframe * CFrame.new(0, -0.5 * size.Y, 0)
2256
                                                                                part_clone.CFrame = cframe * CFrame.new(0, 0.5 * size.Y, 0)
2257
                                                                                part_clone.Parent = model
2258
                                                                                table.insert(parts, part_clone)
2259
                                                                        end
2260
                                                                end
2261
                                                                if size.Z >= fragmentation_size then
2262
                                                                        size = Vector3.new(1, 1, 0.5) * size
2263
                                                                        for part_index = 1, #parts do
2264
                                                                                local part = parts[part_index]
2265
                                                                                local archivable = part.Archivable
2266
                                                                                local cframe = part.CFrame
2267
                                                                                part.FormFactor = "Custom"
2268
                                                                                part.Size = size
2269
                                                                                part.Archivable = true
2270
                                                                                local part_clone = part:Clone()
2271
                                                                                part.Archivable = archivable
2272
                                                                                part_clone.Archivable = archivable
2273
                                                                                part.CFrame = cframe * CFrame.new(0, 0, -0.5 * size.Z)
2274
                                                                                part_clone.CFrame = cframe * CFrame.new(0, 0, 0.5 * size.Z)
2275
                                                                                part_clone.Parent = model
2276
                                                                                table.insert(parts, part_clone)
2277
                                                                        end
2278
                                                                end
2279
                                                                for _, part in ipairs(parts) do
2280
                                                                        part:MakeJoints()
2281
                                                                end
2282
                                                        else
2283
                                                                break
2284
                                                        end
2285
                                                end
2286
                                        else
2287
                                                laser_distance = 9990
2288
                                                break
2289
                                        end
2290
                                end
2291
                        end
2292
                end
2293
                local laser_cframe = magic_circle_cframe * CFrame.Angles(-0.5 * math.pi, 0, 0)
2294
                local laser_width = GraphicalEffects.LASER_WIDTH * opacity * laser_scale
2295
                local laser_mesh_offset = Vector3.new(0, 0.5 * laser_distance, 0)      
2296
                laser_part.CFrame = laser_cframe
2297
                if laser_effects then
2298
                        local laser_effect_data_1, laser_effect_data_2 = laser_effects[1], laser_effects[2]
2299
                        local laser_effect_1, laser_effect_mesh_1 = laser_effect_data_1[1], laser_effect_data_1[2]
2300
                        local laser_effect_2, laser_effect_mesh_2 = laser_effect_data_2[1], laser_effect_data_2[2]
2301
                        laser_effect_1.CFrame = laser_cframe
2302
                        laser_effect_2.CFrame = laser_cframe
2303
                        laser_effect_mesh_1.Offset = laser_mesh_offset
2304
                        laser_effect_mesh_2.Offset = laser_mesh_offset
2305
                        local game_time = time()
2306
                        local effect_scale_1 = 0.5 + 0.5 * math.sin(16 * math.pi * game_time)
2307
                        local effect_scale_2 = 0.5 + 0.5 * math.cos(16 * math.pi * game_time)
2308
                        laser_effect_mesh_1.Scale = 5 * Vector3.new(laser_width * effect_scale_1, laser_distance, laser_width * effect_scale_1)
2309
                        laser_effect_mesh_2.Scale = 5 * Vector3.new(laser_width * effect_scale_2, laser_distance, laser_width * effect_scale_2)
2310
                        laser_width = laser_width * 0.25
2311
                end
2312
                laser_mesh.Offset = laser_mesh_offset                  
2313
                laser_mesh.Scale = 5 * Vector3.new(laser_width, laser_distance, laser_width)
2314
                magic_circle_part.CFrame = magic_circle_cframe
2315
                magic_circle_light.Brightness = opacity
2316
                magic_circle_decal_back.Transparency = transparency
2317
                magic_circle_decal_front.Transparency = transparency
2318
                if light_effects then
2319
                        for index, data in ipairs(laser_lights) do
2320
                                local laser_spotlight_part, laser_spotlight = data[1], data[2]
2321
                                local laser_spotlight_offset = 30 * (index - 1)
2322
                                if laser_spotlight_offset <= laser_distance then
2323
                                        laser_spotlight_part.CFrame = magic_circle_cframe * CFrame.new(0, 0, -laser_spotlight_offset)
2324
                                        laser_spotlight.Brightness = opacity
2325
                                        laser_spotlight.Enabled = true
2326
                                else
2327
                                        laser_spotlight.Enabled = false
2328
                                end
2329
                        end
2330
                end
2331
        end
2332
end
2333
function GraphicalEffects.ShootLaserOfDeath(target, data)
2334
        if chatAdornee then
2335
                data = data or {}
2336
                local brickcolor = data.brickcolor or BrickColor.new("Really black")
2337
                local duration = data.duration or 40
2338
                local fragmentation_size = data.fragmentation_size or 3
2339
                local laser_scale = data.laser_scale or 1
2340
                local light_color = data.light_color or Color3.new(1, 0.5, 1)
2341
                local magic_circle_image = data.magic_circle_image or "rbxassetid://122610943"
2342
                local magic_circle_scale = data.magic_circle_scale or 1
2343
                local sound_volume = data.sound_volume or 1 / 3
2344
                local special_effects = data.special_effects
2345
                local stay = data.stay or 4
2346
                local origin = chatAdornee.CFrame
2347
                local directionOrientation = origin:pointToObjectSpace(target)
2348
                local direction = (target - origin.p).unit
2349
                local magic_circle_position = origin.p + direction * GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE
2350
                local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
2351
                local magic_circle_model = Instance.new("Model")
2352
                local laser_part = Instance.new("Part", magic_circle_model)
2353
                local laser_mesh = Instance.new("CylinderMesh", laser_part)
2354
                local magic_circle_part = Instance.new("Part", magic_circle_model)
2355
                local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
2356
                local magic_circle_light = Instance.new("PointLight", magic_circle_part)
2357
                local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
2358
                local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
2359
                local sound = Instance.new("Sound", magic_circle_part)
2360
                sound.Pitch = 1.25
2361
                sound.SoundId = "rbxassetid://2248511"
2362
                sound.Volume = sound_volume
2363
                magic_circle_model.Archivable = false
2364
                laser_part.Anchored = true
2365
                laser_part.BottomSurface = "Smooth"
2366
                laser_part.BrickColor = brickcolor
2367
                laser_part.CanCollide = false
2368
                laser_part.CFrame = magic_circle_cframe * CFrame.Angles(-0.5 * math.pi, 0, 0)
2369
                laser_part.FormFactor = "Custom"
2370
                laser_part.Locked = true
2371
                laser_part.Size = Vector3.new(0.2, 0.2, 0.2)
2372
                laser_part.TopSurface = "Smooth"
2373
                laser_mesh.Offset = Vector3.new(0, 0, 0)
2374
                laser_mesh.Name = "Mesh"
2375
                laser_mesh.Scale = 5 * laser_scale * Vector3.new(GraphicalEffects.LASER_WIDTH, 0, GraphicalEffects.LASER_WIDTH)
2376
                magic_circle_part.Anchored = true
2377
                magic_circle_part.BottomSurface = "Smooth"
2378
                magic_circle_part.CanCollide = false
2379
                magic_circle_part.CFrame = magic_circle_cframe
2380
                magic_circle_part.FormFactor = "Custom"
2381
                magic_circle_part.Locked = true
2382
                magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
2383
                magic_circle_part.TopSurface = "Smooth"
2384
                magic_circle_part.Transparency = 1
2385
                magic_circle_mesh.Scale = Vector3.new(60, 60, 0) * magic_circle_scale
2386
                magic_circle_light.Color = light_color
2387
                magic_circle_light.Range = 16 * magic_circle_scale
2388
                magic_circle_light.Shadows = true
2389
                magic_circle_decal_back.Face = "Back"
2390
                magic_circle_decal_back.Texture = magic_circle_image
2391
                magic_circle_decal_front.Face = "Front"
2392
                magic_circle_decal_front.Texture = magic_circle_image
2393
                magic_circle_model.Parent = Workspace
2394
                local laser_color = brickcolor.Color
2395
                local laser_lights = {}
2396
                local light_effects = laser_color.r + laser_color.g + laser_color.b > 0.25
2397
                if light_effects then
2398
                        local laser_spotlight_part_template = Instance.new("Part")
2399
                        local laser_spotlight_light_template = Instance.new("SpotLight", laser_spotlight_part_template)
2400
                        laser_spotlight_part_template.Anchored = true
2401
                        laser_spotlight_part_template.Anchored = true
2402
                        laser_spotlight_part_template.BottomSurface = "Smooth"
2403
                        laser_spotlight_part_template.CanCollide = false
2404
                        laser_spotlight_part_template.FormFactor = "Custom"
2405
                        laser_spotlight_part_template.Locked = true
2406
                        laser_spotlight_part_template.Size = Vector3.new(0.2, 0.2, 0.2)
2407
                        laser_spotlight_part_template.TopSurface = "Smooth"
2408
                        laser_spotlight_part_template.Transparency = 1
2409
                        laser_spotlight_light_template.Angle = 45
2410
                        laser_spotlight_light_template.Color = laser_color
2411
                        laser_spotlight_light_template.Enabled = true
2412
                        laser_spotlight_light_template.Name = "Light"
2413
                        laser_spotlight_light_template.Range = 60
2414
                        for index = 1, 40 do
2415
                                local laser_spotlight_part = laser_spotlight_part_template:Clone()
2416
                                laser_spotlight_part.CFrame = magic_circle_cframe * CFrame.new(0, 0, -30 * (index - 1))
2417
                                laser_spotlight_part.Parent = magic_circle_model
2418
                                laser_lights[index] = {laser_spotlight_part, laser_spotlight_part.Light}
2419
                        end
2420
                end
2421
                local laser_effects
2422
                if special_effects then
2423
                        laser_effects = {}
2424
                        local laser_effect_1 = laser_part:Clone()
2425
                        laser_effect_1.BrickColor = special_effects
2426
                        laser_effect_1.Transparency = 0.5
2427
                        local laser_effect_2 = laser_effect_1:Clone()
2428
                        laser_effects[1], laser_effects[2] = {laser_effect_1, laser_effect_1.Mesh}, {laser_effect_2, laser_effect_2.Mesh}
2429
                        laser_effect_1.Parent = magic_circle_model
2430
                        laser_effect_2.Parent = magic_circle_model
2431
                end
2432
                GraphicalEffects.laser_data[{0, directionOrientation, direction, magic_circle_model, laser_part, laser_mesh, magic_circle_part,
2433
 
2434
magic_circle_light, magic_circle_decal_back, magic_circle_decal_front, sound, laser_scale, fragmentation_size, duration, laser_lights, laser_effects, stay,
2435
 
2436
light_effects}] = true
2437
        end
2438
end
2439
2440
function GraphicalEffects.SpawnSapientRock(position)
2441
	local part = Instance.new("Part", Workspace)
2442
	local size = 8 + math.random(0, 5)
2443
	part.BottomSurface = "Smooth"
2444
	part.TopSurface = "Smooth"
2445
	part.Material = "Slate"
2446
	part.Locked = true
2447
	part.Shape = "Ball"
2448
	part.FormFactor = "Custom"
2449
	part.Size = Vector3.new(size, size, size)
2450
	part.Position = position
2451
	local bodypos = Instance.new("BodyPosition", part)
2452
	bodypos.maxForce = Vector3.new(0, 0, 0)
2453
	local angry = false
2454
	local damage_ready = true
2455
	local torso_following
2456
	local torso_changed = -1000
2457
	local touched_conn = part.Touched:connect(function(hit)
2458
		local character = hit.Parent
2459
		if character then
2460
			local humanoid
2461
			for _, child in ipairs(character:GetChildren()) do
2462
				if child:IsA("Humanoid") then
2463
					humanoid = child
2464
					break
2465
				end
2466
			end
2467
			if humanoid then
2468
				if angry then
2469
					if damage_ready then
2470
						damage_ready = false
2471
						humanoid:TakeDamage(100)
2472
						wait(1)
2473
						damage_ready = true
2474
						angry = false
2475
						part.BrickColor = BrickColor.new("Medium stone grey")
2476
					end
2477
				else
2478
					local torso = humanoid.Torso
2479
					if torso then
2480
						torso_following = torso
2481
						torso_changed = tick()
2482
					end
2483
				end
2484
			end
2485
		end
2486
	end)
2487
	TaskScheduler.Start(function()
2488
		while part.Parent == Workspace do
2489
			if torso_following then
2490
				bodypos.position = torso_following.Position
2491
				if tick() - torso_changed > 60 or not torso_following.Parent then
2492
					torso_following = nil
2493
					bodypos.maxForce = Vector3.new(0, 0, 0)
2494
					angry = false
2495
					part.BrickColor = BrickColor.new("Medium stone grey")
2496
				else
2497
					local speed = angry and Vector3.new(16, 16, 16) or Vector3.new(6, 0, 6)
2498
					bodypos.maxForce = part:GetMass() * speed
2499
					if part.Position.Y < -250 then
2500
						part.Velocity = Vector3.new()
2501
						part.Position = torso_following.Position + Vector3.new(0, 80, 0)
2502
						part.BrickColor = BrickColor.new("Bright red")
2503
						angry = true
2504
						torso_changed = tick()
2505
					end
2506
				end
2507
			end
2508
			RunService.Stepped:wait()
2509
		end
2510
		touched_conn:disconnect()
2511
	end)
2512
	TaskScheduler.Start(function()
2513
		while part.Parent == Workspace do
2514
			wait(25 + math.random() * 10)
2515
			local next_size = 8 + math.random() * 5
2516
			if math.random(100) == 1 then
2517
				next_size = next_size * (2 + 6 * math.random())
2518
			end
2519
			next_size = math.floor(next_size + 0.5)
2520
			local start_time = tick()
2521
			local mesh = Instance.new("SpecialMesh", part)
2522
			mesh.MeshType = "Sphere"
2523
			repeat
2524
				local elapsed_time = tick() - start_time
2525
				local alpha = math.cos(elapsed_time * math.pi * 0.5)
2526
				local interpolated_size = size * alpha + next_size * (1 - alpha)
2527
				local size_vector = Vector3.new(interpolated_size, interpolated_size, interpolated_size)
2528
				local cframe = part.CFrame
2529
				part.Size = size_vector
2530
				part.CFrame = cframe
2531
				mesh.Scale = size_vector / part.Size
2532
				RunService.Stepped:wait()
2533
			until tick() - start_time >= 1
2534
			mesh:Destroy()
2535
			local cframe = part.CFrame
2536
			part.Size = Vector3.new(next_size, next_size, next_size)
2537
			part.CFrame = cframe
2538
			size = next_size
2539
		end
2540
	end)
2541
end
2542
2543
function GraphicalEffects.MainLoop()
2544
        RunService.Stepped:wait()
2545
        for data in pairs(GraphicalEffects.magicCircleData) do
2546
                GraphicalEffects.AnimateMagicCircle(data)
2547
        end
2548
        for data in pairs(GraphicalEffects.laser_data) do
2549
                GraphicalEffects.AnimateLaserOfDeath(data)
2550
        end
2551
        for data in pairs(GraphicalEffects.missileData) do
2552
                GraphicalEffects.AnimateMissile(data)
2553
        end
2554
end
2555
TaskScheduler.Start(function()
2556
        while true do
2557
                GraphicalEffects.MainLoop()
2558
        end
2559
end)
2560
2561
PlayerControl = {};
2562
2563
PlayerControl.fly_acceleration = 10
2564
PlayerControl.fly_basespeed = 250
2565
PlayerControl.fly_speed = PlayerControl.fly_basespeed
2566
PlayerControl.featherfallEnabled = true
2567
PlayerControl.pushable = false
2568
PlayerControl.rolling = false
2569
PlayerControl.rollingAngle = 0
2570
PlayerControl.rollingOffset = 0
2571
PlayerControl.rollingMaxOffset = 3
2572
PlayerControl.rollingSpeed = 1 / 50
2573
PlayerControl.characterEnabled = false
2574
PlayerControl.characterMode = "normal"
2575
local character = nil
2576
local flying, flyingMomentum, flyingTilt = false, Vector3.new(), 0
2577
local pose, regeneratingHealth, jumpDebounce = "Standing", false, false
2578
-- TODO: make local variables public
2579
local model, bodyColors, leftArmMesh, leftLegMesh, rightArmMesh, rightLegMesh, torsoMesh, wildcardHat, wildcardHandle, wildcardMesh, pants, shirt, humanoid, 
2580
2581
head, leftArm, leftLeg, rightArm, rightLeg, torso, rootPart, rootJoint, face, soundFreeFalling, soundGettingUp, soundRunning, leftHip, leftShoulder, 
2582
2583
rightHip, rightShoulder, neck, wildcardWeld, feetPart, feetWeld, feetTouchInterest, bodyGyro, bodyVelocity, headMesh, torsoLight
2584
local AnimateCharacter
2585
local UserInterface = game:service'UserInputService'
2586
local chatBubbles = {}
2587
local chatCharacterLimit = 240
2588
function PlayerControl.CreateCharacter()
2589
	local characterMode = PlayerControl.characterMode
2590
	if characterMode == "normal" then
2591
		if not PlayerControl.characterEnabled then
2592
			return
2593
		end
2594
		local appearance = CharacterAppearance.GetDefaultAppearance()
2595
		local active = true
2596
		local torsoCFrame = (torso and torso.CFrame) or PlayerControl.torso_cframe or CFrame.new(0, 10, 0)
2597
		if torsoCFrame.p.Y < -450 then
2598
			torsoCFrame = CFrame.new(0, 10, 0)
2599
		end
2600
		local rootPartCFrame = (rootPart and rootPart.CFrame) or PlayerControl.torso_cframe or CFrame.new(0, 10, 0)
2601
		if rootPartCFrame.p.Y < -450 then
2602
			rootPartCFrame = CFrame.new(0, 10, 0)
2603
		end
2604
		local cameraCFrame = Camera.CoordinateFrame
2605
		local connections = {}
2606
		local feetTouching = {}
2607
		local previousWalkSpeed = 0
2608
		local prevLeftHip, prevLeftShoulder, prevRightHip, prevRightShoulder = leftHip, leftShoulder, rightHip, rightShoulder
2609
		model = Instance.new("Model")
2610
		humanoid = Instance.new("Humanoid", model)
2611
		head = Instance.new("Part", model)
2612
		leftArm = Instance.new("Part", model)
2613
		leftLeg = Instance.new("Part", model)
2614
		rightArm = Instance.new("Part", model)
2615
		rightLeg = Instance.new("Part", model)
2616
		torso = Instance.new("Part", model)
2617
		rootPart = Instance.new("Part", model)
2618
		soundFallingDown = Instance.new("Sound", head)
2619
		soundFreeFalling = Instance.new("Sound", head)
2620
		soundGettingUp = Instance.new("Sound", head)
2621
		soundJumping = Instance.new("Sound", head)
2622
		soundRunning = Instance.new("Sound", head)
2623
		leftHip = Instance.new("Motor", torso)
2624
		leftShoulder = Instance.new("Motor", torso)
2625
		rightHip = Instance.new("Motor", torso)
2626
		rightShoulder = Instance.new("Motor", torso)
2627
		neck = Instance.new("Motor", torso)
2628
		rootJoint = Instance.new("Motor", rootPart)
2629
		feetPart = Instance.new("Part", model)
2630
		feetWeld = Instance.new("Weld", torso)
2631
		bodyGyro = Instance.new("BodyGyro", rootPart)
2632
		bodyVelocity = Instance.new("BodyVelocity", rootPart)
2633
		model.Archivable = false
2634
		model.Name = user_name or Player.Name
2635
		model.PrimaryPart = head
2636
		humanoid.LeftLeg = leftLeg
2637
		humanoid.RightLeg = rightLeg
2638
		humanoid.Torso = rootPart
2639
		head.CFrame = torsoCFrame * CFrame.new(0, 1.5, 0)
2640
		head.FormFactor = "Symmetric"
2641
		head.Locked = true
2642
		head.Name = "Head"
2643
		head.Size = Vector3.new(2, 1, 1)
2644
		head.TopSurface = "Smooth"
2645
		leftArm.CanCollide = false
2646
		leftArm.CFrame = torsoCFrame * CFrame.new(-1.5, 0, 0)
2647
		leftArm.FormFactor = "Symmetric"
2648
		leftArm.Locked = true
2649
		leftArm.Name = "Left Arm"
2650
		leftArm.Size = Vector3.new(1, 2, 1)
2651
		leftLeg.BottomSurface = "Smooth"
2652
		leftLeg.CanCollide = false
2653
		leftLeg.CFrame = torsoCFrame * CFrame.new(-0.5, -2, 0)
2654
		leftLeg.FormFactor = "Symmetric"
2655
		leftLeg.Locked = true
2656
		leftLeg.Name = "Left Leg"
2657
		leftLeg.Size = Vector3.new(1, 2, 1)
2658
		leftLeg.TopSurface = "Smooth"
2659
		rightArm.CanCollide = false
2660
		rightArm.CFrame = torsoCFrame * CFrame.new(1.5, 0, 0)
2661
		rightArm.FormFactor = "Symmetric"
2662
		rightArm.Locked = true
2663
		rightArm.Name = "Right Arm"
2664
		rightArm.Size = Vector3.new(1, 2, 1)
2665
		rightLeg.BottomSurface = "Smooth"
2666
		rightLeg.CanCollide = false
2667
		rightLeg.CFrame = torsoCFrame * CFrame.new(0.5, -2, 0)
2668
		rightLeg.FormFactor = "Symmetric"
2669
		rightLeg.Locked = true
2670
		rightLeg.Name = "Right Leg"
2671
		rightLeg.Size = Vector3.new(1, 2, 1)
2672
		rightLeg.TopSurface = "Smooth"
2673
		torso.CFrame = torsoCFrame
2674
		torso.FormFactor = "Symmetric"
2675
		torso.LeftSurface = "Weld"
2676
		torso.Locked = true
2677
		torso.RightSurface = "Weld"
2678
		torso.Name = "Torso"
2679
		torso.Size = Vector3.new(2, 2, 1)
2680
		rootPart.BottomSurface = "Smooth"
2681
		rootPart.BrickColor = BrickColor.Blue()
2682
		rootPart.CFrame = rootPartCFrame
2683
		rootPart.FormFactor = "Symmetric"
2684
		rootPart.LeftSurface = "Weld"
2685
		rootPart.Locked = true
2686
		rootPart.RightSurface = "Weld"
2687
		rootPart.Name = "HumanoidRootPart"
2688
		rootPart.Size = Vector3.new(2, 2, 1)
2689
		rootPart.TopSurface = "Smooth"
2690
		rootPart.Transparency = 1
2691
		soundFreeFalling.Archivable = false
2692
		soundFreeFalling.SoundId = "rbxasset://sounds/swoosh.wav"
2693
		soundGettingUp.Archivable = false
2694
		soundGettingUp.SoundId = "rbxasset://sounds/hit.wav"
2695
		soundRunning.Archivable = false
2696
		soundRunning.SoundId = "rbxasset://sounds/bfsl-minifigfoots1.mp3"
2697
		soundRunning.Looped = true
2698
		leftHip.C0 = CFrame.new(-1, -1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2699
		leftHip.C1 = CFrame.new(-0.5, 1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2700
		leftHip.MaxVelocity = 0.1
2701
		leftHip.Name = "Left Hip"
2702
		leftHip.Part0 = torso
2703
		leftHip.Part1 = leftLeg
2704
		leftShoulder.C0 = CFrame.new(-1, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2705
		leftShoulder.C1 = CFrame.new(0.5, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2706
		leftShoulder.MaxVelocity = 0.15
2707
		leftShoulder.Name = "Left Shoulder"
2708
		leftShoulder.Part0 = torso
2709
		leftShoulder.Part1 = leftArm
2710
		rightHip.C0 = CFrame.new(1, -1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2711
		rightHip.C1 = CFrame.new(0.5, 1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2712
		rightHip.MaxVelocity = 0.1
2713
		rightHip.Name = "Right Hip"
2714
		rightHip.Part0 = torso
2715
		rightHip.Part1 = rightLeg
2716
		rightShoulder.C0 = CFrame.new(1, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2717
		rightShoulder.C1 = CFrame.new(-0.5, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2718
		rightShoulder.MaxVelocity = 0.15
2719
		rightShoulder.Name = "Right Shoulder"
2720
		rightShoulder.Part0 = torso
2721
		rightShoulder.Part1 = rightArm
2722
		if prevLeftHip then
2723
			leftHip.CurrentAngle = prevLeftHip.CurrentAngle
2724
			leftHip.DesiredAngle = prevLeftHip.DesiredAngle
2725
		end
2726
		if prevLeftShoulder then
2727
			leftShoulder.CurrentAngle = prevLeftShoulder.CurrentAngle
2728
			leftShoulder.DesiredAngle = prevLeftShoulder.DesiredAngle
2729
		end
2730
		if prevRightHip then
2731
			rightHip.CurrentAngle = prevRightHip.CurrentAngle
2732
			rightHip.DesiredAngle = prevRightHip.DesiredAngle
2733
		end
2734
		if prevRightShoulder then
2735
			rightShoulder.CurrentAngle = prevRightShoulder.CurrentAngle
2736
			rightShoulder.DesiredAngle = prevRightShoulder.DesiredAngle
2737
		end
2738
		neck.C0 = CFrame.new(0, 1, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
2739
		neck.C1 = CFrame.new(0, -0.5, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
2740
		neck.Name = "Neck"
2741
		neck.Part0 = torso
2742
		neck.Part1 = head
2743
		rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
2744
		rootJoint.C1 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
2745
		rootJoint.Name = "RootJoint"
2746
		rootJoint.Part0 = rootPart
2747
		rootJoint.Part1 = torso
2748
		feetPart.BottomSurface = "Smooth"
2749
		feetPart.CanCollide = false
2750
		feetPart.CFrame = torsoCFrame * CFrame.new(0, -3.1, 0)
2751
		feetPart.FormFactor = "Custom"
2752
		feetPart.Locked = true
2753
		feetPart.Name = "Platform"
2754
		feetPart.Size = Vector3.new(1.8, 0.2, 0.8)
2755
		feetPart.TopSurface = "Smooth"
2756
		feetPart.Transparency = 1
2757
		feetWeld.C0 = CFrame.new(0, -3, 0)
2758
		feetWeld.C1 = CFrame.new(0, 0.1, 0)
2759
		feetWeld.Name = "PlatformWeld"
2760
		feetWeld.Part0 = torso
2761
		feetWeld.Part1 = feetPart
2762
		table.insert(connections, feetPart.Touched:connect(function(hit)
2763
			feetTouching[hit] = true
2764
		end))
2765
		table.insert(connections, feetPart.TouchEnded:connect(function(hit)
2766
			feetTouching[hit] = nil
2767
		end))
2768
		feetTouchInterest = feetPart:FindFirstChild("TouchInterest")
2769
		bodyGyro.D = 3250
2770
		bodyGyro.P = 400000
2771
		bodyGyro.maxTorque = Vector3.new(1000000000, 0, 1000000000)
2772
		bodyVelocity.P = 5000
2773
		bodyVelocity.maxForce = Vector3.new(0, 0, 0)
2774
		bodyVelocity.velocity = Vector3.new(0, 0, 0)
2775
		torsoLight = Instance.new("PointLight", torso)
2776
		torsoLight.Brightness = 0.4
2777
		torsoLight.Color = Color3.new(1, 1, 1)
2778
		torsoLight.Range = 16
2779
		torsoLight.Shadows = true
2780
		local ff1, ff2, ff3, ff4, ff5, ff6, ff7, ff8, ff9 = Instance.new("ForceField", head), Instance.new("ForceField", leftArm), Instance.new("ForceField", leftLeg), Instance.new("ForceField", rightArm), Instance.new("ForceField", rightLeg), Instance.new("ForceField", torso), Instance.new("ForceField", wildcardHandle), Instance.new("ForceField", feetPart), Instance.new("ForceField", rootPart)
2781
		local forcefields = {[ff1] = head, [ff2] = leftArm, [ff3] = leftLeg, [ff4] = rightArm, [ff5] = rightLeg, [ff6] = torso, [ff7] = wildcardHandle, [ff8] = feetPart, [ff9] = rootPart}	
2782
		local objects = {[humanoid] = true, [head] = true, [leftArm] = true, [leftLeg] = true, [rightArm] = true, [rightLeg] = true, [torso] = true, [rootPart] = true, [rootJoint] = true, [soundFreeFalling] = true, [soundGettingUp] = true, [soundRunning] = true, [leftHip] = true, [leftShoulder] = true, [rightHip] = true, [rightShoulder] = true, [neck] = true, [feetPart] = true, [feetWeld] = true, [feetTouchInterest] = true, [bodyGyro] = true, [bodyVelocity] = true, [ff1] = true, [ff2] = true, [ff3] = true, [ff4] = true, [ff5] = true, [ff6] = true, [ff7] = true, [ff8] = true, [ff9] = true}		
2783
		local tshirtUrl = appearance.tshirt
2784
		if tshirtUrl then
2785
			local tshirt = Instance.new("Decal", torso)
2786
			tshirt.Name = "roblox"
2787
			tshirt.Texture = tshirtUrl
2788
			objects[tshirt] = true
2789
		end
2790
		for _, template in ipairs(appearance.characterObjects) do
2791
			local object = template:Clone()
2792
			local newObjects = {object}
2793
			for _, object in ipairs(newObjects) do
2794
				objects[object] = true
2795
				for _, child in ipairs(object:GetChildren()) do
2796
					table.insert(newObjects, child)
2797
				end				
2798
			end
2799
			if object:IsA("BodyColors") then
2800
				head.BrickColor = object.HeadColor
2801
				leftArm.BrickColor = object.LeftArmColor
2802
				leftLeg.BrickColor = object.LeftLegColor
2803
				rightArm.BrickColor = object.RightArmColor
2804
				rightLeg.BrickColor = object.RightLegColor
2805
				torso.BrickColor = object.TorsoColor
2806
			elseif object:IsA("Hat") then
2807
				local handle = object:FindFirstChild("Handle")
2808
				if handle and handle:IsA("BasePart") then
2809
					local weld = Instance.new("Weld", head)
2810
					weld.C0 = CFrame.new(0, 0.5, 0)
2811
					local attachmentPos = object.AttachmentPos
2812
					local attachmentRight = object.AttachmentRight
2813
					local attachmentUp = object.AttachmentUp
2814
					local attachmentForward = object.AttachmentForward
2815
					weld.C1 = CFrame.new(attachmentPos.X, attachmentPos.Y, attachmentPos.Z,
2816
										 attachmentRight.X, attachmentUp.X, -attachmentForward.X,
2817
										 attachmentRight.Y, attachmentUp.Y, -attachmentForward.Y,
2818
										 attachmentRight.Z, attachmentUp.Z, -attachmentForward.Z)
2819
					weld.Name = "HeadWeld"
2820
					weld.Part0 = head
2821
					weld.Part1 = handle
2822
					handle.Parent = model
2823
					local antiGravity = Instance.new("BodyForce", handle)
2824
					antiGravity.force = Vector3.new(0, handle:GetMass() * 196.2, 0)
2825
					objects[object] = false
2826
					object.Parent = nil
2827
					objects[weld] = true
2828
				end
2829
			end
2830
			object.Parent = model
2831
		end
2832
		local facePresent = false
2833
		local headMeshPresent = false
2834
		for _, template in ipairs(appearance.headObjects) do
2835
			local object = template:Clone()
2836
			local newObjects = {object}
2837
			for _, object in ipairs(newObjects) do
2838
				objects[object] = true
2839
				for _, child in ipairs(object:GetChildren()) do
2840
					table.insert(newObjects, child)
2841
				end				
2842
			end
2843
			if object:IsA("DataModelMesh") then
2844
				headMeshPresent = true
2845
			elseif object:IsA("Decal") then
2846
				facePresent = true
2847
			end
2848
			object.Parent = head
2849
		end
2850
		if not facePresent then
2851
			local face = Instance.new("Decal", head)
2852
			face.Texture = "rbxasset://textures/face.png"
2853
			objects[face] = true
2854
		end
2855
		if not headMeshPresent then
2856
			local headMesh = Instance.new("SpecialMesh", head)
2857
			headMesh.Scale = Vector3.new(1.25, 1.25, 1.25)
2858
			objects[headMesh] = true
2859
		end
2860
		table.insert(connections, model.DescendantAdded:connect(function(object)
2861
			local success, is_localscript = pcall(Game.IsA, object, "LocalScript")
2862
			if success and is_localscript then
2863
				pcall(Utility.SetProperty, object, "Disabled", true)
2864
				local changed_connection = pcall(object.Changed.connect, object.Changed, function(property)
2865
					if property == "Disabled" and not object.Disabled then
2866
						pcall(Utility.SetProperty, object, "Disabled", true)
2867
						object:Destroy()
2868
					end
2869
				end)
2870
			end
2871
			if not objects[object] then
2872
				object:Destroy()
2873
			end
2874
		end))
2875
		model.Parent = Workspace
2876
		Player.Character = model
2877
		Camera.CameraSubject = humanoid
2878
		Camera.CameraType = "Track"
2879
		Camera.CoordinateFrame = cameraCFrame
2880
		local IsStanding
2881
		local RegenerateHealth
2882
		local ResetCharacter
2883
		function IsStanding()
2884
			return not not next(feetTouching)
2885
		end
2886
		function RegenerateHealth()
2887
			if humanoid.Health < 1 then
2888
				humanoid.Health = 100
2889
			elseif not regeneratingHealth then
2890
				regeneratingHealth = true
2891
				local elapsedTime = wait(1)
2892
				regeneratingHealth = false
2893
				if humanoid.Health < 100 then
2894
					humanoid.Health = math.min(humanoid.Health + elapsedTime, 100)
2895
				end
2896
			end
2897
		end
2898
		function ResetCharacter()
2899
			for index, connection in ipairs(connections) do
2900
				connection:disconnect()
2901
			end
2902
			active = false
2903
		end
2904
		table.insert(connections, model.AncestryChanged:connect(ResetCharacter))
2905
		table.insert(connections, model.DescendantRemoving:connect(function(object)
2906
			local parent = forcefields[object]
2907
			if parent then
2908
				forcefields[object] = nil
2909
				local new_forcefield = Instance.new("ForceField")
2910
				forcefields[new_forcefield] = parent
2911
				objects[new_forcefield] = true
2912
				new_forcefield.Parent = parent
2913
			elseif objects[object] then
2914
				ResetCharacter()
2915
			end
2916
		end))
2917
		table.insert(connections, humanoid.HealthChanged:connect(RegenerateHealth))
2918
		table.insert(connections, humanoid.Climbing:connect(function() pose = "Climbing" end))
2919
		table.insert(connections, humanoid.FallingDown:connect(function(state)  pose = "FallingDown" end))
2920
		table.insert(connections, humanoid.FreeFalling:connect(function(state) pose = "FreeFall" if state then soundFreeFalling:Play() else 
2921
2922
soundFreeFalling:Pause() end end))
2923
		table.insert(connections, humanoid.GettingUp:connect(function(state) pose = "GettingUp" if state then soundGettingUp:Play() else 
2924
2925
soundGettingUp:Pause() end end))
2926
		table.insert(connections, humanoid.PlatformStanding:connect(function() pose = "PlatformStanding" end))
2927
		table.insert(connections, humanoid.Seated:connect(function() pose = "Seated" end))
2928
		table.insert(connections, humanoid.Swimming:connect(function(speed) if speed > 0 then pose = "Swimming" else pose = "Standing" end end))
2929
		local previousRootPartCFrame = rootPart.CFrame
2930
		TaskScheduler.Start(function()
2931
			while active do
2932
				local totalTime = TaskScheduler.GetCurrentTime()
2933
				local stepTime = 1 / 60
2934
				if not PlayerControl.characterEnabled then
2935
					ResetCharacter()
2936
					break
2937
				end
2938
				torsoLight.Brightness = 0.5 + 0.15 * math.sin(totalTime * 0.75 * math.pi)
2939
				local featherfallEnabled = PlayerControl.IsFeatherfallEnabled()
2940
				local rootPartCFrame = rootPart.CFrame
2941
				if not jumpDebounce and UserInterface:IsKeyDown(Enum.KeyCode.Space) then
2942
					if humanoid.Sit then
2943
						humanoid.Sit = false
2944
					end
2945
					if IsStanding() then
2946
						jumpDebounce = true
2947
						pose = "Jumping"
2948
						rootPart.Velocity = Vector3.new(rootPart.Velocity.X, 50, rootPart.Velocity.Z)
2949
						torso.Velocity = Vector3.new(torso.Velocity.X, 50, torso.Velocity.Z)						
2950
						TaskScheduler.Schedule(1, function()
2951
							if pose == "Jumping" then
2952
								pose = "FreeFall"
2953
							end
2954
							jumpDebounce = false
2955
							humanoid.Jump = false
2956
						end)
2957
					end
2958
				end
2959
				local cameraCFrame = Camera.CoordinateFrame
2960
				local cameraDirection = cameraCFrame.lookVector
2961
				if flying then
2962
					if PlayerControl.rolling then
2963
						local rootPartCFrame = rootPart.CFrame
2964
						local speed = (rootPartCFrame - rootPartCFrame.p):pointToObjectSpace(rootPart.Velocity).Y
2965
						local decay = 0.5 ^ stepTime
2966
						if math.abs(speed) <= 50 then
2967
							PlayerControl.rollingAngle = (((PlayerControl.rollingAngle + 0.5) % 1 - 0.5) * decay) % 1
2968
							PlayerControl.rollingOffset = PlayerControl.rollingOffset * decay
2969
						else
2970
							PlayerControl.rollingAngle = (PlayerControl.rollingAngle + stepTime * speed * PlayerControl.rollingSpeed) % 1
2971
							PlayerControl.rollingOffset = (PlayerControl.rollingOffset + PlayerControl.rollingMaxOffset * (1 / decay - 1)) * decay
2972
						end
2973
						rootJoint.C0 = (CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0) * CFrame.Angles(PlayerControl.rollingAngle * 2 * math.pi, 0, 0)) * CFrame.new(0, -PlayerControl.rollingOffset, 0)
2974
					else
2975
						rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
2976
						PlayerControl.rollingAngle = 0
2977
						PlayerControl.rollingOffset = 0
2978
					end
2979
					rightShoulder.MaxVelocity = 0.5
2980
					leftShoulder.MaxVelocity = 0.5
2981
					rightShoulder.DesiredAngle = 0
2982
					leftShoulder.DesiredAngle = 0
2983
					rightHip.DesiredAngle = 0
2984
					leftHip.DesiredAngle = 0
2985
					bodyGyro.D = 500
2986
					bodyGyro.P = 1e6
2987
					bodyGyro.maxTorque = Vector3.new(1e6, 1e6, 1e6)
2988
					bodyVelocity.P = 1250
2989
					bodyVelocity.maxForce = Vector3.new(1e6, 1e6, 1e6)
2990
					local movementRight = 0
2991
					local movementForward = 0
2992
					local movementUp = 0
2993
					if UserInterface:IsKeyDown(Enum.KeyCode.A) and not UserInterface:IsKeyDown(Enum.KeyCode.D) then
2994
						movementRight = -1
2995
					elseif UserInterface:IsKeyDown(Enum.KeyCode.D) then
2996
						movementRight = 1
2997
					end
2998
					if UserInterface:IsKeyDown(Enum.KeyCode.W) then
2999
						movementUp = 0.2
3000
						if not UserInterface:IsKeyDown(Enum.KeyCode.S) then
3001
							movementForward = -1
3002
						end
3003
					elseif UserInterface:IsKeyDown(Enum.KeyCode.S) then
3004
						movementForward = 1
3005
					end
3006
					local movement = PlayerControl.fly_acceleration * cameraCFrame:vectorToWorldSpace(Vector3.new(movementRight, movementUp, movementForward))
3007
					local previousMomentum = flyingMomentum
3008
					local previousTilt = flyingTilt
3009
					flyingMomentum = movement + flyingMomentum * (1 - PlayerControl.fly_acceleration / PlayerControl.fly_speed)
3010
					flyingTilt = ((flyingMomentum * Vector3.new(1, 0, 1)).unit:Cross((previousMomentum * Vector3.new(1, 0, 1)).unit)).Y
3011
					if flyingTilt ~= flyingTilt or flyingTilt == math.huge then
3012
						flyingTilt = 0
3013
					end
3014
					local absoluteTilt = math.abs(flyingTilt)
3015
					if absoluteTilt > 0.06 or absoluteTilt < 0.0001 then
3016
						if math.abs(previousTilt) > 0.0001 then
3017
							flyingTilt = previousTilt * 0.9
3018
						else
3019
							flyingTilt = 0
3020
						end
3021
					else
3022
						flyingTilt = previousTilt * 0.77 + flyingTilt * 0.25
3023
					end
3024
					previousTilt = flyingTilt
3025
					if flyingMomentum.magnitude < 0.1 then
3026
						flyingMomentum = Vector3.new(0, 0, 0)
3027
--						bodyGyro.cframe = cameraCFrame
3028
					else
3029
						local momentumOrientation = CFrame.new(Vector3.new(0, 0, 0), flyingMomentum)
3030
						local tiltOrientation = CFrame.Angles(0, 0, -20 * flyingTilt)
3031
						bodyGyro.cframe = momentumOrientation * tiltOrientation * CFrame.Angles(-0.5 * math.pi * math.min(flyingMomentum.magnitude / PlayerControl.fly_speed, 1), 0, 0)
3032
					end
3033
					bodyVelocity.velocity = flyingMomentum + Vector3.new(0, 0.15695775618683547, 0)
3034
					rootPart.Velocity = flyingMomentum
3035
					previousMomentum = flyingMomentum
3036
				else
3037
					rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
3038
					PlayerControl.rollingAngle = 0
3039
					PlayerControl.rollingOffset = 0
3040
					bodyGyro.D = 3250
3041
					bodyGyro.P = 400000
3042
					bodyVelocity.P = 5000
3043
					local cameraDirection = cameraCFrame.lookVector
3044
					local walkDirection = Vector3.new(0, 0, 0)
3045
					local walkSpeed = 16
3046
					if UserInterface:IsKeyDown(Enum.KeyCode.W) then
3047
						if UserInterface:IsKeyDown(Enum.KeyCode.A) then
3048
							walkDirection = Vector3.new(cameraDirection.X + cameraDirection.Z, 0, cameraDirection.Z - cameraDirection.X).unit
3049
						elseif UserInterface:IsKeyDown(Enum.KeyCode.D) then
3050
							walkDirection = Vector3.new(cameraDirection.X - cameraDirection.Z, 0, cameraDirection.Z + cameraDirection.X).unit
3051
						else
3052
							walkDirection = Vector3.new(cameraDirection.X, 0, cameraDirection.Z).unit
3053
						end
3054
					elseif UserInterface:IsKeyDown(Enum.KeyCode.S) then
3055
						if UserInterface:IsKeyDown(Enum.KeyCode.A) then
3056
							walkDirection = Vector3.new(-cameraDirection.X + cameraDirection.Z, 0, -cameraDirection.Z - cameraDirection.X).unit
3057
						elseif UserInterface:IsKeyDown(Enum.KeyCode.D) then
3058
							walkDirection = Vector3.new(-cameraDirection.X - cameraDirection.Z, 0, -cameraDirection.Z + cameraDirection.X).unit
3059
						else
3060
							walkDirection = Vector3.new(-cameraDirection.X, 0, -cameraDirection.Z).unit
3061
						end
3062
					elseif UserInterface:IsKeyDown(Enum.KeyCode.A) then
3063
						walkDirection = Vector3.new(cameraDirection.Z, 0, -cameraDirection.X).unit
3064
					elseif UserInterface:IsKeyDown(Enum.KeyCode.D) then
3065
						walkDirection = Vector3.new(-cameraDirection.Z, 0, cameraDirection.X).unit
3066
					else
3067
						walkSpeed = 0
3068
					end
3069
					if walkSpeed ~= previousWalkSpeed then
3070
						if walkSpeed > 0 then
3071
							soundRunning:Play()
3072
						else
3073
							soundRunning:Pause()
3074
						end
3075
					end
3076
					if walkSpeed > 0 then
3077
						if pose ~= "Jumping" then
3078
							if IsStanding() then
3079
								pose = "Running"
3080
							else
3081
								pose = "FreeFall"
3082
							end
3083
						end
3084
						bodyGyro.cframe = CFrame.new(Vector3.new(), walkDirection)
3085
						bodyGyro.maxTorque = Vector3.new(1000000000, 1000000000, 1000000000)
3086
						bodyVelocity.maxForce = Vector3.new(1000000, maxForceY, 1000000)
3087
					else
3088
						if pose ~= "Jumping" then
3089
							if IsStanding() then
3090
								pose = "Standing"
3091
							else
3092
								pose = "FreeFall"
3093
							end
3094
						end
3095
						-- TODO: find and fix bug that causes torso to rotate back to some angle
3096
						bodyGyro.maxTorque = Vector3.new(1000000000, 1000000000, 1000000000) -- Vector3.new(1000000000, 0, 1000000000)
3097
						if PlayerControl.pushable then
3098
							bodyVelocity.maxForce = Vector3.new(0, 0, 0)
3099
						else
3100
							bodyVelocity.maxForce = Vector3.new(1000000, 0, 1000000)
3101
						end
3102
					end
3103
					if featherfallEnabled then
3104
						local velocity = rootPart.Velocity
3105
						if velocity.Y > 50 then
3106
							rootPart.Velocity = Vector3.new(velocity.X, 50, velocity.Z)
3107
						elseif velocity.Y < -50 then
3108
							rootPart.Velocity = Vector3.new(velocity.X, -50, velocity.Z)
3109
						end
3110
						local distanceVector = rootPartCFrame.p - previousRootPartCFrame.p
3111
						local offsetX, offsetY, offsetZ = distanceVector.X, distanceVector.Y, distanceVector.Z
3112
						local MAX_MOVEMENT = 50 * 0.03333333507180214
3113
						if offsetX > MAX_MOVEMENT then
3114
							offsetX = MAX_MOVEMENT
3115
						elseif offsetX < -MAX_MOVEMENT then
3116
							offsetX = -MAX_MOVEMENT
3117
						end
3118
						if offsetY > MAX_MOVEMENT then
3119
							offsetY = MAX_MOVEMENT
3120
						elseif offsetY < -MAX_MOVEMENT then
3121
							offsetY = -MAX_MOVEMENT
3122
						end
3123
						if offsetZ > MAX_MOVEMENT then
3124
							offsetZ = MAX_MOVEMENT
3125
						elseif offsetZ < -MAX_MOVEMENT then
3126
							offsetZ = -MAX_MOVEMENT
3127
						end
3128
						local offset = Vector3.new(offsetX, offsetY, offsetZ)
3129
						if offset ~= distanceVector then
3130
							rootPartCFrame = previousRootPartCFrame + offset
3131
							--rootPart.CFrame = rootPartCFrame
3132
						end
3133
					end
3134
					local walkingVelocity = walkDirection * walkSpeed
3135
					bodyVelocity.velocity = walkingVelocity
3136
					if not jumpDebounce and math.abs(rootPart.Velocity.Y) <= 0.1 then
3137
						rootPart.Velocity = Vector3.new(walkingVelocity.X, rootPart.Velocity.Y, walkingVelocity.Z)
3138
					end
3139
					previousWalkSpeed = walkSpeed
3140
					if pose == "Jumping" or jumpDebounce then
3141
						rightShoulder.MaxVelocity = 0.5
3142
						leftShoulder.MaxVelocity = 0.5
3143
						rightShoulder.DesiredAngle = 3.14
3144
						leftShoulder.DesiredAngle = -3.14
3145
						rightHip.DesiredAngle = 0
3146
						leftHip.DesiredAngle = 0
3147
					elseif pose == "FreeFall" then
3148
						rightShoulder.MaxVelocity = 0.5
3149
						leftShoulder.MaxVelocity = 0.5
3150
						rightShoulder.DesiredAngle = 3.14
3151
						leftShoulder.DesiredAngle = -3.14
3152
						rightHip.DesiredAngle = 0
3153
						leftHip.DesiredAngle = 0
3154
					elseif pose == "Seated" then
3155
						rightShoulder.MaxVelocity = 0.15
3156
						leftShoulder.MaxVelocity = 0.15
3157
						rightShoulder.DesiredAngle = 3.14 / 2
3158
						leftShoulder.DesiredAngle = -3.14 / 2
3159
						rightHip.DesiredAngle = 3.14 / 2
3160
						leftHip.DesiredAngle = -3.14 / 2
3161
					else
3162
						local climbFudge = 0
3163
						local amplitude
3164
						local frequency
3165
						if pose == "Running" then
3166
							rightShoulder.MaxVelocity = 0.15
3167
							leftShoulder.MaxVelocity = 0.15
3168
							amplitude = 1
3169
							frequency = 9
3170
						elseif (pose == "Climbing") then
3171
							rightShoulder.MaxVelocity = 0.5 
3172
							leftShoulder.MaxVelocity = 0.5
3173
							amplitude = 1
3174
							frequency = 9
3175
							climbFudge = 3.14
3176
						else
3177
							amplitude = 0.1
3178
							frequency = 1
3179
						end
3180
						local desiredAngle = amplitude * math.sin(totalTime * frequency)
3181
						rightShoulder.DesiredAngle = desiredAngle + climbFudge
3182
						leftShoulder.DesiredAngle = desiredAngle - climbFudge
3183
						rightHip.DesiredAngle = -desiredAngle
3184
						leftHip.DesiredAngle = -desiredAngle
3185
					end
3186
				end
3187
				previousRootPartCFrame = rootPartCFrame
3188
				RunService.RenderStepped:wait()
3189
			end
3190
			if model.Parent ~= nil then
3191
				model.Parent = nil
3192
			end
3193
			PlayerControl.CreateCharacter()
3194
		end)
3195
		humanoid.Health = 100
3196
		character = model
3197
		chatAdornee = head
3198
	elseif characterMode == "pyramid" then
3199
		if PlayerControl.characterEnabled then
3200
			Camera.CameraType = "Fixed"
3201
			PyramidCharacter.camera_distance = (Camera.Focus.p - Camera.CoordinateFrame.p).magnitude
3202
			PyramidCharacter.camera_position = Camera.Focus.p
3203
			PyramidCharacter.Teleport(Camera.Focus.p)
3204
			PyramidCharacter.visible = true
3205
			Player.Character = nil
3206
		else
3207
			PyramidCharacter.visible = false
3208
		end
3209
	end
3210
end
3211
function PlayerControl.GetCharacter()
3212
	return character
3213
end
3214
function PlayerControl.GetHead()
3215
	local characterMode = PlayerControl.characterMode
3216
	if characterMode == "normal" then
3217
		return head
3218
	elseif characterMode == "pyramid" then
3219
		return PyramidCharacter.core
3220
	end
3221
end
3222
function PlayerControl.GetHumanoid()
3223
	return humanoid
3224
end
3225
function PlayerControl.GetRootPart()
3226
	return rootPart
3227
end
3228
function PlayerControl.GetTorso()
3229
	return torso
3230
end
3231
function PlayerControl.IsEnabled()
3232
	return PlayerControl.characterEnabled
3233
end
3234
function PlayerControl.IsFeatherfallEnabled()
3235
	return PlayerControl.featherfallEnabled
3236
end
3237
function PlayerControl.IsPushable()
3238
	return PlayerControl.pushable
3239
end
3240
function PlayerControl.IsRolling()
3241
	return PlayerControl.rolling
3242
end
3243
function PlayerControl.ResetCharacter()
3244
	if character and character.Parent then
3245
		character.Parent = nil
3246
	end
3247
	PyramidCharacter.visible = false
3248
end
3249
function PlayerControl.SetEnabled(state, no_animation)
3250
	state = not not state
3251
	if state ~= PlayerControl.characterEnabled then
3252
		PlayerControl.characterEnabled = state
3253
		local characterMode = PlayerControl.characterMode
3254
		if characterMode == "normal" then
3255
			local torso = PlayerControl.GetRootPart()
3256
			local rootPart = PlayerControl.GetRootPart()
3257
			if rootPart then
3258
				if PlayerControl.characterEnabled then
3259
					local torso_cframe = Camera.Focus:toWorldSpace(PlayerControl.hide_torso_object_cframe)
3260
					PlayerControl.torso_cframe = torso_cframe
3261
					torso.CFrame = torso_cframe
3262
					rootPart.CFrame = torso_cframe
3263
				else
3264
					PlayerControl.hide_torso_object_cframe = Camera.Focus:toObjectSpace(rootPart.CFrame)
3265
				end
3266
			else
3267
				PlayerControl.torso_cframe = Camera.Focus
3268
			end
3269
			if PlayerControl.characterEnabled then
3270
				PlayerControl.CreateCharacter()
3271
				RunService.Stepped:wait()
3272
				coroutine.yield()
3273
				if not no_animation then
3274
					GraphicalEffects.CrystalRing({base_part = PlayerControl.GetTorso(), crystal_color = BrickColor.new("Institutional white"), float_duration = 2})
3275
				end		
3276
			else
3277
				Player.Character = nil
3278
				Camera.CameraType = "Fixed"
3279
				if not no_animation then
3280
					GraphicalEffects.CrystalRing({position = PlayerControl.GetTorso().Position, crystal_color = BrickColor.new("Institutional white"), float_duration = 2})
3281
				end
3282
			end
3283
		else
3284
			if state then
3285
				PlayerControl.CreateCharacter()
3286
				RunService.Stepped:wait()
3287
				coroutine.yield()
3288
				if not no_animation then
3289
					GraphicalEffects.CrystalRing({base_part = PyramidCharacter.core, crystal_color = BrickColor.new("Institutional white"), float_duration = 2})
3290
				end
3291
			else
3292
				PyramidCharacter.visible = false
3293
				if not no_animation then
3294
					GraphicalEffects.CrystalRing({position = PyramidCharacter.core.Position, crystal_color = BrickColor.new("Institutional white"), float_duration = 2})
3295
				end
3296
			end
3297
		end
3298
	end
3299
end
3300
function PlayerControl.SetFeatherfallEnabled(state)
3301
	state = not not state
3302
	if state ~= PlayerControl.featherfallEnabled then
3303
		PlayerControl.featherfallEnabled = state
3304
		if state then
3305
			Logger.print("Info", "Featherfall enabled in PlayerControl")
3306
		else
3307
			Logger.print("Info", "Featherfall disabled in PlayerControl")
3308
		end
3309
	end
3310
end
3311
function PlayerControl.SetPushable(state)
3312
	state = not not state
3313
	if state ~= PlayerControl.pushable then
3314
		PlayerControl.pushable = state
3315
		if state then
3316
			Logger.print("Info", "Pushing enabled in PlayerControl")
3317
		else
3318
			Logger.print("Info", "Pushing disabled in PlayerControl")
3319
		end
3320
	end
3321
end
3322
function PlayerControl.SetRolling(state)
3323
	state = not not state
3324
	if state ~= PlayerControl.rolling then
3325
		PlayerControl.rolling = state
3326
		if state then
3327
			Logger.print("Info", "Rolling fly mode enabled in PlayerControl")
3328
		else
3329
			Logger.print("Info", "Rolling fly mode disabled in PlayerControl")
3330
		end
3331
	end
3332
end
3333
function PlayerControl.StartFlying()
3334
	PlayerControl.fly_speed = PlayerControl.fly_basespeed
3335
	if torso then
3336
		flyingMomentum = torso.Velocity + torso.CFrame.lookVector * 3 + Vector3.new(0, 10, 0)
3337
	else
3338
		flyingMomentum = Vector3.new()
3339
	end
3340
	flyingTilt = 0
3341
	flying = true
3342
end
3343
function PlayerControl.StopFlying()
3344
	if bodyGyro.cframe then
3345
		local lookVector = bodyGyro.cframe.lookVector
3346
		if lookVector.X ~= 0 or lookVector.Z ~= 0 then
3347
			bodyGyro.cframe = CFrame.new(Vector3.new(), Vector3.new(lookVector.X, 0, lookVector.Z))
3348
		end
3349
	end
3350
	flying = false
3351
end
3352
local previousTime = 0
3353
3354
ControllerCommands = {};
3355
3356
ControllerCommands = {};
3357
3358
ControllerCommands.BALEFIRE_SPEED = 40
3359
function ControllerCommands.BalefireAtMouse()
3360
        local head = chatAdornee
3361
        if head then
3362
                local target = Mouse.Hit.p
3363
                local origin = head.Position
3364
                local direction = (target - origin).unit
3365
                local explosionCount = 0
3366
                local animation_frame = 0
3367
                local magic_circle_position = origin + direction * 4
3368
                local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
3369
                local magic_circle_part = Instance.new("Part")
3370
                local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
3371
                local magic_circle_light = Instance.new("PointLight", magic_circle_part)
3372
                local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
3373
                local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
3374
                magic_circle_part.Anchored = true
3375
                magic_circle_part.Archivable = false
3376
                magic_circle_part.BottomSurface = "Smooth"
3377
                magic_circle_part.CanCollide = false
3378
                magic_circle_part.CFrame = magic_circle_cframe
3379
                magic_circle_part.FormFactor = "Custom"
3380
                magic_circle_part.Locked = true
3381
                magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
3382
                magic_circle_part.TopSurface = "Smooth"
3383
                magic_circle_part.Transparency = 1
3384
                magic_circle_mesh.Scale = Vector3.new(60, 60, 0)
3385
                magic_circle_light.Color = Color3.new(1, 0.5, 1)
3386
                magic_circle_light.Range = 16
3387
                magic_circle_light.Shadows = true
3388
                magic_circle_decal_back.Face = "Back"
3389
                magic_circle_decal_back.Texture = "rbxassetid://122610943"
3390
                magic_circle_decal_front.Face = "Front"
3391
                magic_circle_decal_front.Texture = "rbxassetid://122610943"
3392
                local function NextExplosion()
3393
                        explosionCount = explosionCount + 1
3394
                        Instance.new("Explosion", Workspace).Position = origin + direction * (explosionCount * 8 + 4)
3395
                end
3396
                local function AnimateMagicCircle()
3397
                        animation_frame = animation_frame + 1
3398
                        local transparency = (animation_frame / 40) ^ 3
3399
                        if animation_frame == 40 then
3400
                                pcall(Game.Destroy, magic_circle_part)
3401
                        else
3402
                                if magic_circle_part.Parent ~= Workspace then
3403
                                        pcall(Utility.SetProperty, magic_circle_part, "Parent", Workspace)
3404
                                end
3405
                                head = PlayerControl.GetHead()
3406
                                if head then
3407
                                        magic_circle_position = head.Position + direction * 4
3408
                                end
3409
                                magic_circle_part.CFrame = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0,
3410
 
3411
math.tau * animation_frame / 40 * 1.5)
3412
                                magic_circle_light.Brightness = 1 - transparency
3413
                                magic_circle_decal_back.Transparency = transparency
3414
                                magic_circle_decal_front.Transparency = transparency
3415
                        end
3416
                end
3417
                magic_circle_part.Parent = Workspace
3418
                for i = 1, 40 do
3419
                        Delay((i - 1) / ControllerCommands.BALEFIRE_SPEED, NextExplosion)
3420
                        Delay((i - 1) / 30, AnimateMagicCircle)
3421
                end
3422
                for i = 1, 20 do
3423
                        Delay((i - 1) / ControllerCommands.BALEFIRE_SPEED, NextExplosion)
3424
                end
3425
        end
3426
end
3427
function ControllerCommands.ControlRandomDummy()
3428
        local dummies = {}
3429
        local numDummies = 0
3430
        for _, character in ipairs(Workspace:GetChildren()) do
3431
                local name = tostring(character)
3432
                if name == "???" or name == "Dummy" then
3433
                        local head, humanoid
3434
                        for _, child in ipairs(character:GetChildren()) do
3435
                                local className = child.ClassName
3436
                                if className == "Part" and tostring(child) == "Head" then
3437
                                        head = child
3438
                                        if humanoid then
3439
                                                break
3440
                                        end
3441
                                elseif className == "Humanoid" then
3442
                                        if child.Health > 0 then
3443
                                                humanoid = child
3444
                                                if head then
3445
                                                        break
3446
                                                end
3447
                                        else
3448
                                                break
3449
                                        end
3450
                                end
3451
                        end
3452
                        if head and humanoid then
3453
                                numDummies = numDummies + 1
3454
                                dummies[numDummies] = {character, head, humanoid}
3455
                        end
3456
                end
3457
        end
3458
        if numDummies > 0 then
3459
                local dummy = dummies[math.random(numDummies)]
3460
                Player.Character = dummy[1]
3461
                chatAdornee = dummy[2]
3462
                Camera.CameraSubject = dummy[3]
3463
                Camera.CameraType = "Track"
3464
        end
3465
end
3466
function ControllerCommands.Decalify(textures, exclusion)
3467
        local objects = Workspace:GetChildren()
3468
        for _, object in ipairs(objects) do
3469
                if not exclusion[object] then
3470
                        for _, child in ipairs(object:GetChildren()) do
3471
                                objects[#objects + 1] = child
3472
                        end
3473
                        if object:IsA("BasePart") then
3474
                                local texture = textures[math.random(#textures)]
3475
                                local face_left = Instance.new("Decal", object)
3476
                                face_left.Face = Enum.NormalId.Left
3477
                                face_left.Texture = texture
3478
                                local face_right = Instance.new("Decal", object)
3479
                                face_right.Face = Enum.NormalId.Right
3480
                                face_right.Texture = texture
3481
                                local face_bottom = Instance.new("Decal", object)
3482
                                face_bottom.Face = Enum.NormalId.Bottom
3483
                                face_bottom.Texture = texture
3484
                                local face_top = Instance.new("Decal", object)
3485
                                face_top.Face = Enum.NormalId.Top
3486
                                face_top.Texture = texture
3487
                                local face_front = Instance.new("Decal", object)
3488
                                face_front.Face = Enum.NormalId.Front
3489
                                face_front.Texture = texture
3490
                                local face_back = Instance.new("Decal", object)
3491
                                face_back.Face = Enum.NormalId.Back
3492
                                face_back.Texture = texture
3493
                        end
3494
                end
3495
        end
3496
end
3497
3498
function ControllerCommands.ExplodeAtMouse()
3499
        local explosion = Instance.new("Explosion")
3500
        explosion.Position = Mouse.Hit.p
3501
        explosion.Parent = Workspace
3502
end
3503
function ControllerCommands.LaserAtMouse()
3504
        GraphicalEffects.ShootLaserOfDeath(Mouse.Hit.p)
3505
end
3506
function ControllerCommands.BigLaser(target)
3507
        GraphicalEffects.ShootLaserOfDeath(target, {brickcolor = BrickColor.new("New Yeller"), duration = 80, fragmentation_size = 6,laser_scale = 30, light_color = Color3.new(1, 0.5, 0), magic_circle_image = "rbxassetid://126561317", magic_circle_scale = 1.5, sound_volume = 1,special_effects = BrickColor.new("Deep orange"), stay = 2})
3508
end
3509
function ControllerCommands.BigLaserAtMouse()
3510
        ControllerCommands.BigLaser(Mouse.Hit.p)
3511
end
3512
function ControllerCommands.ShootMissile(targetPart, pointOnPart, direction)
3513
        GraphicalEffects.ShootMissile(targetPart, pointOnPart, direction)
3514
end
3515
function ControllerCommands.ShootMissileAtMouse(amount, spread, delayTime)
3516
        local exclusionList = {}
3517
        local playerHead = PlayerControl.GetHead()
3518
        local playerTorso = PlayerControl.GetTorso()
3519
        if playerHead and playerTorso then
3520
                exclusionList[playerTorso] = true
3521
                local humanoid, torso = Utility.FindHumanoidClosestToRay(Mouse.UnitRay, exclusionList)
3522
                local targetPart, pointOnPart
3523
                if humanoid and torso then
3524
                        targetPart, pointOnPart = torso, Vector3.new()
3525
                else
3526
                        local target = Mouse.Target
3527
                        if target then
3528
                                targetPart, pointOnPart = target, target.CFrame:pointToObjectSpace(Mouse.Hit.p)
3529
                        else
3530
                                return
3531
                        end
3532
                end
3533
                if targetPart then
3534
                        local direction = (Mouse.Hit.p - playerHead.Position).unit
3535
                        delayTime = delayTime or 0
3536
                        for index = 1, amount do
3537
                                local angles = math.tau * (index - 0.5) * spread / amount * Vector3.new(math.random() - 0.5, math.random() - 0.5,math.random() - 0.5).unit
3538
                                TaskScheduler.Schedule(delayTime * (index - 1), ControllerCommands.ShootMissile, targetPart, pointOnPart, CFrame.Angles(angles.X, angles.Y, angles.Z) * direction)
3539
                        end
3540
                end
3541
        end
3542
end
3543
function ControllerCommands.ShootMissileAroundMouse(amount, offset, delayTime)
3544
        local exclusionList = {}
3545
        local playerHead = PlayerControl.GetHead()
3546
        local playerTorso = PlayerControl.GetTorso()
3547
        if playerHead and playerTorso then
3548
                exclusionList[playerTorso] = true
3549
                local humanoid, torso = Utility.FindHumanoidClosestToRay(Mouse.UnitRay, exclusionList)
3550
                local targetPart, pointOnPart
3551
                if humanoid and torso then
3552
                        targetPart, pointOnPart = torso, Vector3.new()
3553
                else
3554
                        local target = Mouse.Target
3555
                        if target then
3556
                                targetPart, pointOnPart = target, target.CFrame:pointToObjectSpace(Mouse.Hit.p)
3557
                        else
3558
                                return
3559
                        end
3560
                end
3561
                if targetPart then
3562
                        delayTime = delayTime or 0
3563
                        local index = 1
3564
                        local targetPoint = targetPart.CFrame * pointOnPart
3565
                        local rotation_offset_angles = math.tau * Vector3.new(math.random() - 0.5, math.random() - 0.5, 0).unit
3566
                        local rotation_offset = CFrame.Angles(rotation_offset_angles.x, rotation_offset_angles.y, 0)
3567
                        local angle_x = 0
3568
                        local angle_x_step = math.tau / math.phi
3569
                        for i = 1, 8 * amount do
3570
                                angle_x = angle_x + angle_x_step
3571
                                local direction = rotation_offset * (CFrame.Angles(0, math.tau * index / amount, 0) * CFrame.Angles(angle_x, 0,0).lookVector)
3572
                                local blocked = Workspace:FindPartOnRay(Ray.new(targetPoint, direction * offset), targetPart.Parent)
3573
                                if not blocked then
3574
                                        local p0, p1, p2, p3 = targetPart, pointOnPart, direction, offset; GraphicalEffects.ShootMissile(p0, p1, p2, function() return p0 end, p3, true)
3575
                                        index = index + 1
3576
                                        if index > amount then
3577
                                                break
3578
                                        end
3579
                                end
3580
                        end
3581
                end
3582
        end
3583
end
3584
3585
function ControllerCommands.HugeExplosionOfDoom(position)
3586
        local connections = {}
3587
        local parts = {}
3588
        local cframe = CFrame.new(position)
3589
        local function ExplosionHit(part)
3590
                if part:GetMass() < 10000 and part.Parent ~= Camera then
3591
                        parts[part] = true
3592
                        part.Anchored = true
3593
                        part:BreakJoints()
3594
                        part.BrickColor = BrickColor.new("Instituational white")
3595
                end
3596
        end
3597
        for i = 1, 4 do
3598
                local quantity = 0.5 * i * (1 + i)
3599
                local fraction = math.tau / quantity
3600
                for x = 1, quantity do
3601
                        for y = 1, quantity do
3602
                                local explosion = Instance.new("Explosion")
3603
                                connections[#connections + 1] = explosion.Hit:connect(ExplosionHit)
3604
                                explosion.BlastRadius = 5
3605
                                explosion.Position = cframe * (CFrame.Angles(fraction * x, fraction * y, 0) * Vector3.new((i - 1) * 6, 0, 0))
3606
                                explosion.Parent = Workspace
3607
                        end
3608
                end
3609
                wait(0.075)
3610
        end
3611
        for part in pairs(parts) do
3612
                for _, child in ipairs(part:GetChildren()) do
3613
                        if child:IsA("BodyMover") then
3614
                                child:Destroy()
3615
                        end
3616
                end
3617
                local mass = part:GetMass()
3618
                local velocity = CFrame.Angles(math.tau * math.random(), math.tau * math.random(), 0) * Vector3.new(25, 0, 0)
3619
                local bodythrust = Instance.new("BodyThrust")
3620
                bodythrust.force = mass * -velocity
3621
                bodythrust.Parent = part
3622
                local bodyforce = Instance.new("BodyForce")
3623
                bodyforce.force = mass * Vector3.new(0, 196.2, 0)
3624
                bodyforce.Parent = part
3625
                part.Anchored = false
3626
                part.Reflectance = 1
3627
                part.RotVelocity = math.tau * Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5)
3628
                part.Transparency = 0.5
3629
                part.Velocity = (part.CFrame - part.Position) * velocity
3630
        end
3631
        for _, connection in ipairs(connections) do
3632
                connection:disconnect()
3633
        end
3634
        for i = 0, 99 do
3635
                Delay(i / 10, function()
3636
                        for part in pairs(parts) do
3637
                                local new_transparency = 0.5 * (1 + i / 50)
3638
                                part.Reflectance = 0.98 * part.Reflectance
3639
                                if new_transparency > part.Transparency then
3640
                                        part.Transparency = new_transparency
3641
                                end
3642
                        end
3643
                end)
3644
        end
3645
        Delay(10, function()
3646
                for part in pairs(parts) do
3647
                        pcall(part.Destroy, part)
3648
                end
3649
        end)
3650
end
3651
function ControllerCommands.HugeExplosionOfDoomAtMouse()
3652
        ControllerCommands.HugeExplosionOfDoom(Mouse.Hit.p)
3653
end
3654
3655
function ControllerCommands.SpaceHyperBeam(asd)
3656
        GraphicalEffects.SpaceHyperBeam(asd)
3657
end
3658
function ControllerCommands.SpaceHyperBeamAtMouse()
3659
        ControllerCommands.SpaceHyperBeam(Mouse.Hit.p)
3660
end
3661
function ControllerCommands.ConcentratedSpaceHyperBeamAtMouse()
3662
        local p = Mouse.Hit.p; for i = 1, 50 do GraphicalEffects.SpaceHyperBeam(p) end
3663
end
3664
3665
function ControllerCommands.TeleportCharacterToMouse()
3666
        if PlayerControl.IsEnabled() then
3667
                local torso = PlayerControl.GetTorso()
3668
                if torso then
3669
                        local pos = Mouse.Hit.p + Vector3.new(0, 5, 0)
3670
                        torso.CFrame = CFrame.new(pos, pos + torso.CFrame.lookVector)
3671
                end
3672
        else
3673
                local new_focus_position = Mouse.Hit.p
3674
                local direction_vector = Camera.CoordinateFrame.lookVector
3675
                local new_focus = CFrame.new(new_focus_position, new_focus_position + direction_vector)
3676
                Camera.CoordinateFrame = new_focus * CFrame.new(0, 0, 25)
3677
                Camera.Focus = new_focus
3678
        end
3679
end
3680
3681
AdvancedGUI = {};
3682
3683
if not AdvancedGUI.GUI_BASE_COLOR then
3684
	AdvancedGUI.GUI_BASE_COLOR = Color3.new(0, 0, 0)
3685
end
3686
function AdvancedGUI.GenerateChatColor(speakerName)
3687
	local chatColor = ChatColor.Get(speakerName).Color
3688
	local brightness = chatColor.r + chatColor.g + chatColor.b
3689
	if brightness < 1.5 then
3690
		chatColor = Color3.new(math.min(1, 0.4 + chatColor.r), math.min(1, 0.4 + chatColor.g), math.min(1, 0.4 + chatColor.b))
3691
	else
3692
		chatColor = Color3.new(math.min(1, 0.05 + chatColor.r), math.min(1, 0.05 + chatColor.g), math.min(1, 0.05 + chatColor.b))
3693
	end
3694
	return chatColor
3695
end
3696
GuiBase = {}
3697
GuiBase.__index = GuiBase
3698
function GuiBase:new(data)
3699
	local instance = setmetatable({}, self)
3700
	instance:Init(data)
3701
	return instance
3702
end
3703
function GuiBase:Destroy()
3704
	if self.parent then
3705
		self.parent.children[self] = nil
3706
	end
3707
	for child in pairs(self.children) do
3708
		child:Destroy()
3709
	end
3710
	self.m_base_instance:Destroy()
3711
end
3712
function GuiBase:GetContentInstance(child)
3713
	return self.m_base_instance
3714
end
3715
function GuiBase:Init()
3716
	self.children = {}
3717
end
3718
function GuiBase:IsA(className)
3719
	return className == "GuiBase"
3720
end
3721
function GuiBase:SetParent(parent)
3722
	if parent ~= self.parent then
3723
		if self.parent then
3724
			self.parent.children[self] = nil
3725
		end
3726
		self.parent = parent
3727
		if parent then
3728
			parent.children[self] = true
3729
			self.m_base_instance.Parent = parent:GetContentInstance()
3730
		else
3731
			self.m_base_instance.Parent = nil
3732
		end
3733
	end
3734
end
3735
GuiObject = setmetatable({}, GuiBase)
3736
GuiObject.__index = GuiObject
3737
function GuiObject:Destroy()
3738
	self.DragBegin:disconnect()
3739
	self.DragMove:disconnect()
3740
	self.DragStopped:disconnect()
3741
	self.MouseButton1Click:disconnect()
3742
	self.MouseButton1Down:disconnect()
3743
	self.MouseButton1Up:disconnect()
3744
	self.MouseButton2Down:disconnect()
3745
	self.MouseButton2Up:disconnect()
3746
	self.MouseEnter:disconnect()
3747
	self.MouseLeave:disconnect()
3748
	GuiBase.Destroy(self)
3749
end
3750
function GuiObject:GetAbsolutePosition()
3751
	return self.m_base_instance.AbsolutePosition
3752
end
3753
function GuiObject:GetAbsoluteSize()
3754
	return self.m_base_instance.AbsoluteSize
3755
end
3756
function GuiObject:GetPosition()
3757
	return self.position
3758
end
3759
function GuiObject:GetSize()
3760
	return self.size
3761
end
3762
function GuiObject:Init()
3763
	GuiBase.Init(self)
3764
	self.mouseDown = false
3765
	self.mouseOver = false
3766
	self.DragBegin = RbxUtility.CreateSignal()
3767
	self.DragMove = RbxUtility.CreateSignal()
3768
	self.DragStopped = RbxUtility.CreateSignal()
3769
	self.MouseButton1Click = RbxUtility.CreateSignal()
3770
	self.MouseButton1Down = RbxUtility.CreateSignal()
3771
	self.MouseButton1Up = RbxUtility.CreateSignal()
3772
	self.MouseButton2Down = RbxUtility.CreateSignal()
3773
	self.MouseButton2Up = RbxUtility.CreateSignal()
3774
	self.MouseEnter = RbxUtility.CreateSignal()
3775
	self.MouseLeave = RbxUtility.CreateSignal()
3776
end
3777
function GuiObject:IsA(className)
3778
	return className == "GuiObject" or GuiBase.IsA(self, className)
3779
end
3780
function GuiObject:SetActive(active)
3781
	if active ~= self.active then
3782
		self.active = active
3783
	end
3784
end
3785
function GuiObject:SetBackgroundTransparency(backgroundTransparency)
3786
	if backgroundTransparency ~= self.backgroundTransparency then
3787
		self.backgroundTransparency = backgroundTransparency
3788
		self.m_base_instance.BackgroundTransparency = backgroundTransparency
3789
	end
3790
end
3791
function GuiObject:SetColor(color)
3792
	if color ~= self.color then
3793
		self.color = color
3794
		self.m_base_instance.BackgroundColor3 = color
3795
	end
3796
end
3797
function GuiObject:SetPosition(position)
3798
	if position ~= self.position then
3799
		self.position = position
3800
		self.m_base_instance.Position = position
3801
	end
3802
end
3803
function GuiObject:SetSize(size)
3804
	if size ~= self.size then
3805
		self.size = size
3806
		self.m_base_instance.Size = size
3807
	end
3808
end
3809
function GuiObject:SetVisible(visible)
3810
	if visible ~= self.visible then
3811
		self.visible = visible
3812
		self.m_base_instance.Visible = visible
3813
	end
3814
end
3815
function GuiObject:SetZIndex(zIndex)
3816
	local stack = {self.m_base_instance}
3817
	repeat
3818
		local object = stack[#stack]
3819
		stack[#stack] = nil
3820
		for _, child in ipairs(object:GetChildren()) do
3821
			stack[#stack + 1] = child
3822
		end
3823
		object.ZIndex = zIndex
3824
	until #stack == 0
3825
end
3826
GuiServiceClass = setmetatable({}, GuiBase)
3827
GuiServiceClass.__index = GuiServiceClass
3828
function GuiServiceClass:CreateTextArea(text, font, fontSize, textColor3, textXAlignment, textYAlignment, maxWidth, minWidth)
3829
	local totalHeight = 0
3830
	local frame = Instance.new("Frame")
3831
	frame.BackgroundTransparency = 1
3832
	local label = Instance.new("TextLabel")
3833
	label.BackgroundTransparency = 1
3834
	label.Font = font
3835
	label.FontSize = fontSize
3836
	label.TextColor3 = textColor3
3837
	label.TextTransparency = 1
3838
	label.TextWrapped = true
3839
	label.TextXAlignment = textXAlignment
3840
	label.TextYAlignment = textYAlignment
3841
	label.Parent = self.guiFrame
3842
	local index = 1
3843
	while true do
3844
		local length = #text - index + 1
3845
		if length > 1024 then
3846
			length = 1024
3847
			local textBlock = string.sub(text, index, index + length - 1)
3848
			label.Text = textBlock
3849
			local height = 0
3850
			local width = maxWidth
3851
			repeat
3852
				height = height + 20
3853
				label.Size = UDim2.new(0, width, 0, height)
3854
			until label.TextFits
3855
			repeat
3856
				height = height - 1
3857
				label.Size = UDim2.new(0, width, 0, height)
3858
			until not label.TextFits
3859
			repeat
3860
				length = length - 10
3861
				label.Text = string.sub(text, index, index + length - 1)
3862
			until label.TextFits
3863
			repeat
3864
				length = length + 1
3865
				label.Text = string.sub(text, index, index + length - 1)
3866
			until not label.TextFits
3867
			local overflowCharacter = string.sub(text, index + length - 1, index + length - 1)
3868
			length = length - 1
3869
			label.Text = string.sub(text, index, index + length - 1)
3870
			if overflowCharacter == "\n" then
3871
				index = index + 1
3872
			end
3873
			repeat
3874
				height = height - 1
3875
				label.Size = UDim2.new(0, width, 0, height)
3876
			until not label.TextFits
3877
			height = height + 1
3878
			local blockLabel = label:Clone()
3879
			blockLabel.Position = UDim2.new(0, 0, 0, totalHeight)
3880
			blockLabel.Size = UDim2.new(1, 0, 0, height)
3881
			blockLabel.Parent = frame
3882
			totalHeight = totalHeight + height
3883
			index = index + length
3884
		else
3885
			local textBlock = string.sub(text, index)
3886
			label.Text = textBlock
3887
			local height = 0
3888
			local width = maxWidth
3889
			repeat
3890
				height = height + 20
3891
				label.Size = UDim2.new(0, width, 0, height)
3892
			until label.TextFits
3893
			repeat
3894
				height = height - 1
3895
				label.Size = UDim2.new(0, width, 0, height)
3896
			until not label.TextFits
3897
			height = height + 1
3898
			if index == 1 then
3899
				repeat
3900
					width =  width - 10
3901
					label.Size = UDim2.new(0, width, 0, height)
3902
				until width < minWidth or not label.TextFits
3903
				width = math.max(width, minWidth - 1)
3904
				repeat
3905
					width =  width + 1
3906
					label.Size = UDim2.new(0, width, 0, height)
3907
				until label.TextFits
3908
			end
3909
			local blockLabel = label:Clone()
3910
			blockLabel.Position = UDim2.new(0, 0, 0, totalHeight)
3911
			blockLabel.Size = UDim2.new(1, 0, 0, height)
3912
			blockLabel.Parent = frame
3913
			label:Destroy()
3914
			frame.Size = UDim2.new(0, width, 0, totalHeight + height)
3915
			return frame
3916
		end
3917
	end
3918
end
3919
function GuiServiceClass:Destroy()
3920
	self.running = false
3921
	self.cameraPart:Destroy()
3922
	self.cameraConnection:disconnect()
3923
	self.keyDownConnection:disconnect()
3924
	self.mouseButton1DownConnection:disconnect()
3925
	self.mouseButton1UpConnection:disconnect()
3926
	self.mouseButton2DownConnection:disconnect()
3927
	self.mouseButton2UpConnection:disconnect()
3928
	self.mouseMoveConnection:disconnect()
3929
	self.steppedConnection:disconnect()
3930
end
3931
function GuiServiceClass:GetMousePosition()
3932
	local mouse = self.mouse
3933
	return mouse.X, mouse.Y -- mouse.X, mouse.Y + 2 -- return mouse.X - 2, mouse.Y - 3
3934
end
3935
function GuiServiceClass:GetTextBounds(text, font, fontSize, alignX, alignY, width)
3936
	local tempLabel = self.tempLabel
3937
	tempLabel.Font = font
3938
	tempLabel.FontSize = fontSize
3939
	tempLabel.Size = UDim2.new(0, width, 0, 4096)
3940
	tempLabel.Text = text
3941
	tempLabel.TextXAlignment = alignX
3942
	tempLabel.TextYAlignment = alignY
3943
	local textBounds = tempLabel.TextBounds
3944
	tempLabel.Text = ""
3945
	return textBounds
3946
end
3947
function GuiServiceClass:Init(data)
3948
	GuiBase.Init(self)
3949
	local _ = string.char
3950
	local camera = data.Camera
3951
	local mouse = data.Mouse
3952
	local cameraPart = Instance.new("Part")
3953
	local billboardGui = Instance.new("BillboardGui", cameraPart)
3954
	guiFrame = Instance.new("Frame", billboardGui)
3955
	cameraPart.Anchored = true
3956
	cameraPart.BottomSurface = "Smooth"
3957
	cameraPart.CanCollide = false
3958
--	cameraPart.CFrame = CFrame.new(16384, 16384, 16384)
3959
	cameraPart.FormFactor = "Custom"
3960
	cameraPart.Locked = true
3961
	cameraPart.Size = Vector3.new(0.2, 0.2, 0.2)
3962
	cameraPart.TopSurface = "Smooth"
3963
	cameraPart.Transparency = 1
3964
	billboardGui.Adornee = cameraPart
3965
	billboardGui.AlwaysOnTop = true
3966
--	billboardGui.ExtentsOffset = Vector3.new(-16384, -16384, -16384)
3967
	guiFrame.BackgroundTransparency = 1
3968
	cameraPart.Parent = camera
3969
	self.running = true
3970
	self.m_base_instance = guiFrame
3971
	self.billboardGui = billboardGui
3972
	self.cameraPart = cameraPart
3973
	self.tempLabel = RBXInstance.new "TextLabel" {
3974
		BackgroundTransparency = 1,
3975
		TextTransparency = 1,
3976
		TextWrapped = true,
3977
		Parent = guiFrame
3978
	}
3979
	self.mnemonics = {}
3980
	self.visible = true
3981
	self.camera = camera
3982
	self.mouse = mouse
3983
	self.cameraConnection = camera.Changed:connect(function(property)
3984
		self:UpdateView()
3985
		if property == "CameraType" then
3986
			if camera.CameraType ~= Enum.CameraType.Track and camera.CameraType ~= Enum.CameraType.Fixed then
3987
				camera.CameraType = Enum.CameraType.Track
3988
			end
3989
		elseif property == "CoordinateFrame" and camera.CameraType ~= Enum.CameraType.Fixed then
3990
			local cframe, focus = camera.CoordinateFrame, camera.Focus
3991
			local watchOffset = focus.p - cframe.p
3992
			local error = watchOffset.unit - cframe.lookVector
3993
			if error.magnitude >= 1e-3 then
3994
				local head = PlayerControl.GetHead()
3995
				local time1, velocity1
3996
				if head then
3997
					time1 = time()
3998
					velocity1 = head.Velocity
3999
				end
4000
				if camera.Changed:wait() == "CoordinateFrame" then
4001
					local position = cframe.p
4002
					if head then
4003
						local time2 = time()
4004
						local velocity2 = head.Velocity
4005
						position = position + 0.5 * (velocity1 + velocity2) * (time2 - time1)
4006
					end
4007
					camera.CoordinateFrame = CFrame.new(position, camera.Focus.p)
4008
				end
4009
			end
4010
		end
4011
	end)
4012
	self.keyDownConnection = mouse.KeyDown:connect(function(key) self:KeyDown(key) end)
4013
	self.mouseButton1DownConnection = mouse.Button1Down:connect(function() self:MouseButton1Down() end)
4014
	self.mouseButton1UpConnection = mouse.Button1Up:connect(function() self:MouseButton1Up() end)
4015
	self.mouseButton2DownConnection = mouse.Button2Down:connect(function() self:MouseButton2Down() end)
4016
	self.mouseButton2UpConnection = mouse.Button2Up:connect(function() self:MouseButton2Up() end)
4017
	self.mouseMoveConnection = mouse.Move:connect(function() self:MouseMove() end)
4018
	self.steppedConnection = RunService.RenderStepped:connect(function() self:UpdateObjects() self:UpdateView() end)
4019
	self.mousePreviousPosition = Vector2.new(self:GetMousePosition())
4020
end
4021
function GuiServiceClass:IsA(className)
4022
	return className == "GuiService" or GuiBase.IsA(self, className)
4023
end
4024
function GuiServiceClass:KeyDown(key)
4025
	local mnemonicButton = self.mnemonics[string.upper(key)]
4026
	if mnemonicButton then
4027
		mnemonicButton.Activated:fire()
4028
	end
4029
end
4030
function GuiServiceClass:MouseButton1Down()
4031
	local mouse = self.mouse
4032
	local mouseX, mouseY = self:GetMousePosition()
4033
	local stack = {self}
4034
	local dragObjects = {}
4035
	self.dragObjects = dragObjects
4036
	while #stack > 0 do
4037
		local object = stack[#stack]
4038
		stack[#stack] = nil
4039
		if object.visible then
4040
			for child in pairs(object.children) do
4041
				stack[#stack + 1] = child
4042
			end
4043
			if object.active then
4044
				local position = object:GetAbsolutePosition()
4045
				local size = object:GetAbsoluteSize()
4046
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
4047
					object.mouseDown = true
4048
					dragObjects[object] = true
4049
					local mouseButton1Down = object.MouseButton1Down
4050
					if mouseButton1Down then
4051
						mouseButton1Down:fire()
4052
						if object.autoButtonColor then
4053
							local color = object.color
4054
							local transparency = object.backgroundTransparency
4055
							object.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min(color.g + 
4056
4057
0.3, 1), math.min(color.b + 0.3, 1))
4058
							object.m_base_instance.BackgroundTransparency = transparency
4059
						end
4060
					end
4061
					object.DragBegin:fire()
4062
				end
4063
			end
4064
		end
4065
	end
4066
	self.mousePreviousPosition = Vector2.new(mouseX, mouseY)
4067
end
4068
function GuiServiceClass:MouseButton1Up()
4069
	local mouse = self.mouse
4070
	local mouseX, mouseY = self:GetMousePosition()
4071
	local stack = {self}
4072
	while #stack > 0 do
4073
		local object = stack[#stack]
4074
		stack[#stack] = nil
4075
		if object.visible then
4076
			for child in pairs(object.children) do
4077
				stack[#stack + 1] = child
4078
			end
4079
			if object.active then
4080
				local position = object:GetAbsolutePosition()
4081
				local size = object:GetAbsoluteSize()
4082
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
4083
					object.MouseButton1Up:fire()
4084
				end
4085
			end
4086
		end
4087
	end
4088
	local dragObjects = self.dragObjects
4089
	self.dragObjects = nil
4090
	if dragObjects then
4091
		for dragObject in pairs(dragObjects) do
4092
			dragObject.mouseDown = false
4093
			local position = dragObject:GetAbsolutePosition()
4094
			local size = dragObject:GetAbsoluteSize()
4095
			if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
4096
				dragObject.MouseButton1Click:fire()
4097
				local activated = dragObject.Activated
4098
				if activated then
4099
					activated:fire()
4100
				end
4101
			end
4102
			dragObject.DragStopped:fire()
4103
			if dragObject.autoButtonColor then
4104
				if dragObject.mouseOver then
4105
					local color = dragObject.color
4106
					local transparency = dragObject.backgroundTransparency
4107
					dragObject.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max(color.g - 0.3, 0), 
4108
4109
math.max(color.b - 0.3, 0))
4110
					dragObject.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.2)
4111
				else
4112
					dragObject.m_base_instance.BackgroundColor3 = dragObject.color
4113
					dragObject.m_base_instance.BackgroundTransparency = dragObject.backgroundTransparency
4114
				end
4115
			end
4116
			self.dragObject = nil
4117
		end
4118
	end
4119
end
4120
function GuiServiceClass:MouseButton2Down()
4121
	local mouse = self.mouse
4122
	local mouseX, mouseY = self:GetMousePosition()
4123
	local stack = {self}
4124
	while #stack > 0 do
4125
		local object = stack[#stack]
4126
		stack[#stack] = nil
4127
		if object.visible then
4128
			for child in pairs(object.children) do
4129
				stack[#stack + 1] = child
4130
			end
4131
			if object.active then
4132
				local position = object:GetAbsolutePosition()
4133
				local size = object:GetAbsoluteSize()
4134
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
4135
					local mouseButton2Down = object.MouseButton2Down
4136
					if mouseButton2Down then
4137
						mouseButton2Down:fire()
4138
					end
4139
				end
4140
			end
4141
		end
4142
	end
4143
	self.mousePreviousPosition = Vector2.new(mouseX, mouseY)
4144
end
4145
function GuiServiceClass:MouseButton2Up()
4146
	local mouse = self.mouse
4147
	local mouseX, mouseY = self:GetMousePosition()
4148
	local stack = {self}
4149
	while #stack > 0 do
4150
		local object = stack[#stack]
4151
		stack[#stack] = nil
4152
		if object.visible then
4153
			for child in pairs(object.children) do
4154
				stack[#stack + 1] = child
4155
			end
4156
			if object.active then
4157
				local position = object:GetAbsolutePosition()
4158
				local size = object:GetAbsoluteSize()
4159
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
4160
					local mouseButton2Up = object.MouseButton2Up
4161
					if mouseButton2Up then
4162
						mouseButton2Up:fire()
4163
					end
4164
				end
4165
			end
4166
		end
4167
	end
4168
end
4169
function GuiServiceClass:MouseMove()
4170
	self:UpdateObjects()
4171
	local dragObjects = self.dragObjects
4172
	if dragObjects then
4173
		for dragObject in pairs(dragObjects) do
4174
			local mouse = self.mouse
4175
			local mousePosition = Vector2.new(self:GetMousePosition())
4176
			dragObject.DragMove:fire(mousePosition - self.mousePreviousPosition)
4177
			self.mousePreviousPosition = mousePosition
4178
		end
4179
	end
4180
end
4181
function GuiServiceClass:SetMnemonic(mnemonic, button)
4182
	self.mnemonics[mnemonic] = button
4183
end
4184
function GuiServiceClass:UpdateObjects()
4185
	local mouse = self.mouse
4186
	local mouseX, mouseY = self:GetMousePosition()
4187
	local stack = {self}
4188
	while #stack > 0 do
4189
		local object = stack[#stack]
4190
		stack[#stack] = nil
4191
		if object.visible then
4192
			for child in pairs(object.children) do
4193
				stack[#stack + 1] = child
4194
			end
4195
			if object.active then
4196
				local position = object:GetAbsolutePosition()
4197
				local size = object:GetAbsoluteSize()
4198
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
4199
					if not object.mouseOver then
4200
						object.mouseOver = true
4201
						object.MouseEnter:fire()
4202
						if object.autoButtonColor then
4203
							local color = object.color
4204
							local transparency = object.backgroundTransparency
4205
							if object.mouseDown then
4206
								object.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min(color.g + 0.3, 1), math.min(color.b + 0.3, 1))
4207
								object.m_base_instance.BackgroundTransparency = transparency
4208
							else
4209
								object.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max(color.g - 0.3, 0), math.max(color.b - 0.3, 0))
4210
								object.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.2)
4211
							end
4212
						end
4213
					end
4214
				else
4215
					if object.mouseOver then
4216
						object.mouseOver = false
4217
						object.MouseLeave:fire()
4218
						if object.autoButtonColor then
4219
							object.m_base_instance.BackgroundColor3 = object.color
4220
							object.m_base_instance.BackgroundTransparency = object.backgroundTransparency
4221
						end
4222
					end
4223
				end
4224
			end
4225
		end
4226
	end
4227
end
4228
function GuiServiceClass:UpdateView()
4229
	local billboardGui = self.billboardGui
4230
	local guiFrame = self.m_base_instance
4231
	local camera = self.camera
4232
	local mouse = self.mouse
4233
	local cameraCFrame = CFrame.new(camera.CoordinateFrame.p, camera.Focus.p) -- camera.CoordinateFrame
4234
	local viewSizeX, viewSizeY = mouse.ViewSizeX, mouse.ViewSizeY
4235
	local previousViewSize = self.viewSize
4236
	if not previousViewSize or ((viewSizeX ~= 0 or viewSizeY ~= 0) and (viewSizeX ~= previousViewSize.X or viewSizeY ~= previousViewSize.Y)) then
4237
		self.viewSize = {X = viewSizeX, Y = viewSizeY}
4238
		local viewSizeUDim2 = UDim2.new(0, viewSizeX, 0, viewSizeY)
4239
		billboardGui.Size = viewSizeUDim2
4240
		guiFrame.Size = viewSizeUDim2
4241
		-- FIXME:
4242
		-- After the 15th of July 2014, there came an offset at the Y thingy out of nowhere so I accomodated for that.
4243
		billboardGui.SizeOffset = Vector2.new(0.5 / viewSizeX, (0.5 + 10) / viewSizeY)
4244
	end
4245
	--billboardGui.SizeOffset = Vector2.new()
4246
	billboardGui.StudsOffset = (cameraCFrame - cameraCFrame.p):inverse() * cameraCFrame.p - Vector3.new(0, 0, 1)
4247
end
4248
GuiService = GuiServiceClass:new {
4249
	Camera = Camera,
4250
	Mouse = Mouse
4251
}
4252
GuiFrame = setmetatable({}, GuiObject)
4253
GuiFrame.__index = GuiFrame
4254
GuiFrame.__default = {__index = {
4255
	Active = false,
4256
	BackgroundTransparency = 0.75,
4257
	BorderSize = 4,
4258
	BorderTransparency = 0.75,
4259
	Color = AdvancedGUI.GUI_BASE_COLOR,
4260
	Position = UDim2.new(0, 0, 0, 0),
4261
	Size = UDim2.new(0, 52, 0, 52),
4262
	Visible = true
4263
}}
4264
function GuiFrame:Destroy()
4265
	GuiObject.Destroy(self)
4266
end
4267
function GuiFrame:GetContentInstance()
4268
	return self.m_content_frame
4269
end
4270
function GuiFrame:Init(data)
4271
	GuiObject.Init(self)
4272
	setmetatable(data, GuiFrame.__default)
4273
	local leftBorderFrameLeft = RBXInstance.new "Frame" {
4274
		BackgroundColor3 = Color3.new(0, 0, 0),
4275
		BorderSizePixel = 0,
4276
		Size = UDim2.new(0, 1, 1, -1)
4277
	}
4278
	local leftBorderFrameCenter = RBXInstance.new "Frame" {
4279
		BackgroundColor3 = Color3.new(1, 1, 1),
4280
		BorderSizePixel = 0,
4281
		Position = UDim2.new(0, 1, 0, 1)
4282
	}
4283
	local leftBorderFrameRight = RBXInstance.new "Frame" {
4284
		BackgroundColor3 = Color3.new(0, 0, 0),
4285
		BorderSizePixel = 0
4286
	}
4287
	local rightBorderFrameRight = RBXInstance.new "Frame" {
4288
		BackgroundColor3 = Color3.new(0, 0, 0),
4289
		BorderSizePixel = 0,
4290
		Position = UDim2.new(1, -1, 0, 1),
4291
		Size = UDim2.new(0, 1, 1, -1)
4292
	}
4293
	local rightBorderFrameCenter = RBXInstance.new "Frame" {
4294
		BackgroundColor3 = Color3.new(1, 1, 1),
4295
		BorderSizePixel = 0
4296
	}
4297
	local rightBorderFrameLeft = RBXInstance.new "Frame" {
4298
		BackgroundColor3 = Color3.new(0, 0, 0),
4299
		BorderSizePixel = 0
4300
	}
4301
	local bottomBorderFrameBottom = RBXInstance.new "Frame" {
4302
		BackgroundColor3 = Color3.new(0, 0, 0),
4303
		BorderSizePixel = 0,
4304
		Position = UDim2.new(0, 0, 1, -1),
4305
		Size = UDim2.new(1, -1, 0, 1)
4306
	}
4307
	local bottomBorderFrameCenter = RBXInstance.new "Frame" {
4308
		BackgroundColor3 = Color3.new(1, 1, 1),
4309
		BorderSizePixel = 0
4310
	}
4311
	local bottomBorderFrameTop = RBXInstance.new "Frame" {
4312
		BackgroundColor3 = Color3.new(0, 0, 0),
4313
		BorderSizePixel = 0
4314
	}
4315
	local topBorderFrameTop = RBXInstance.new "Frame" {
4316
		BackgroundColor3 = Color3.new(0, 0, 0),
4317
		BorderSizePixel = 0,
4318
		Position = UDim2.new(0, 1, 0, 0),
4319
		Size = UDim2.new(1, -1, 0, 1)
4320
	}
4321
	local topBorderFrameCenter = RBXInstance.new "Frame" {
4322
		BackgroundColor3 = Color3.new(1, 1, 1),
4323
		BorderSizePixel = 0
4324
	}
4325
	local topBorderFrameBottom = RBXInstance.new "Frame" {
4326
		BackgroundColor3 = Color3.new(0, 0, 0),
4327
		BorderSizePixel = 0
4328
	}
4329
	local border_frame = RBXInstance.new "Frame" {
4330
		BackgroundTransparency = 1,
4331
		Size = UDim2.new(1, 0, 1, 0),
4332
		leftBorderFrameLeft,
4333
		leftBorderFrameCenter,
4334
		leftBorderFrameRight,
4335
		rightBorderFrameLeft,
4336
		rightBorderFrameCenter,
4337
		rightBorderFrameRight,
4338
		bottomBorderFrameBottom,
4339
		bottomBorderFrameCenter,
4340
		bottomBorderFrameTop,
4341
		topBorderFrameBottom,
4342
		topBorderFrameCenter,
4343
		topBorderFrameTop
4344
	}
4345
	local contentFrame = RBXInstance.new "Frame" {
4346
		BackgroundTransparency = 1,
4347
		BorderSizePixel = 0,
4348
		ClipsDescendants = true,
4349
		Size = UDim2.new(1, 0, 1, 0)
4350
	}
4351
	local base_frame = RBXInstance.new "Frame" {
4352
		BorderSizePixel = 0,
4353
		border_frame,
4354
		contentFrame
4355
	}
4356
	self.m_base_instance = base_frame
4357
	self.m_content_frame = contentFrame
4358
	self.m_border_frame = border_frame
4359
	self.leftBorderFrameLeft = leftBorderFrameLeft
4360
	self.leftBorderFrameCenter = leftBorderFrameCenter
4361
	self.leftBorderFrameRight = leftBorderFrameRight
4362
	self.rightBorderFrameLeft = rightBorderFrameLeft
4363
	self.rightBorderFrameCenter = rightBorderFrameCenter
4364
	self.rightBorderFrameRight = rightBorderFrameRight
4365
	self.bottomBorderFrameBottom = bottomBorderFrameBottom
4366
	self.bottomBorderFrameCenter = bottomBorderFrameCenter
4367
	self.bottomBorderFrameTop = bottomBorderFrameTop
4368
	self.topBorderFrameBottom = topBorderFrameBottom
4369
	self.topBorderFrameCenter = topBorderFrameCenter
4370
	self.topBorderFrameTop = topBorderFrameTop
4371
	self:SetActive(data.Active)
4372
	self:SetBackgroundTransparency(data.BackgroundTransparency)
4373
	self:SetBorderSize(data.BorderSize)
4374
	self:SetBorderTransparency(data.BorderTransparency)
4375
	self:SetColor(data.Color)
4376
	self:SetPosition(data.Position)
4377
	self:SetSize(data.Size)
4378
	self:SetVisible(data.Visible)
4379
	self:SetParent(data.Parent)
4380
end
4381
function GuiFrame:IsA(className)
4382
	return className == "GuiFrame" or GuiObject.IsA(self, className)
4383
end
4384
function GuiFrame:SetBorderSize(border_size)
4385
	border_size = math.max(math.floor(border_size + 0.5), 0)
4386
	if border_size ~= self.m_border_size then
4387
		self.m_border_size = border_size
4388
		local border_frame = self.m_border_frame
4389
		local contentFrame = self.m_content_frame
4390
		local leftBorderFrameCenter = self.leftBorderFrameCenter
4391
		local leftBorderFrameRight = self.leftBorderFrameRight
4392
		local rightBorderFrameCenter = self.rightBorderFrameCenter
4393
		local rightBorderFrameLeft = self.rightBorderFrameLeft
4394
		local bottomBorderFrameCenter = self.bottomBorderFrameCenter
4395
		local bottomBorderFrameTop = self.bottomBorderFrameTop
4396
		local topBorderFrameCenter = self.topBorderFrameCenter
4397
		local topBorderFrameBottom = self.topBorderFrameBottom
4398
		contentFrame.Position = UDim2.new(0, border_size, 0, border_size)
4399
		contentFrame.Size = UDim2.new(1, -2 * border_size, 1, -2 * border_size)
4400
		local inner_visible = border_size > 0
4401
		if self.leftBorderFrameLeft.Visible ~= inner_visible then
4402
			self.rightBorderFrameRight.Visible = inner_visible
4403
			self.bottomBorderFrameBottom.Visible = inner_visible
4404
			self.topBorderFrameTop.Visible = inner_visible
4405
		end
4406
		local outer_visible = border_size > 1
4407
		if leftBorderFrameCenter.Visible ~= outer_visible then
4408
			leftBorderFrameCenter.Visible = outer_visible
4409
			leftBorderFrameRight.Visible = outer_visible
4410
			rightBorderFrameCenter.Visible = outer_visible
4411
			rightBorderFrameLeft.Visible = outer_visible
4412
			bottomBorderFrameCenter.Visible = outer_visible
4413
			bottomBorderFrameTop.Visible = outer_visible
4414
			topBorderFrameCenter.Visible = outer_visible
4415
			topBorderFrameBottom.Visible = outer_visible
4416
		end
4417
		if outer_visible then
4418
			leftBorderFrameCenter.Size = UDim2.new(0, border_size - 2, 1, -border_size)
4419
			leftBorderFrameRight.Position = UDim2.new(0, border_size - 1, 0, border_size - 1)
4420
			leftBorderFrameRight.Size = UDim2.new(0, 1, 1, 1 - 2 * border_size)
4421
			rightBorderFrameCenter.Position = UDim2.new(1, 1 - border_size, 0, border_size - 1)
4422
			rightBorderFrameCenter.Size = UDim2.new(0, border_size - 2, 1, -border_size)
4423
			rightBorderFrameLeft.Position = UDim2.new(1, -border_size, 0, border_size)
4424
			rightBorderFrameLeft.Size = UDim2.new(0, 1, 1, 1 - 2 * border_size)
4425
			bottomBorderFrameCenter.Position = UDim2.new(0, 1, 1, 1 - border_size)
4426
			bottomBorderFrameCenter.Size = UDim2.new(1, -border_size, 0, border_size - 2)
4427
			bottomBorderFrameTop.Position = UDim2.new(0, border_size - 1, 1, -border_size)
4428
			bottomBorderFrameTop.Size = UDim2.new(1, 1 - 2 * border_size, 0, 1)
4429
			topBorderFrameCenter.Position = UDim2.new(0, border_size - 1, 0, 1)
4430
			topBorderFrameCenter.Size = UDim2.new(1, -border_size, 0, border_size - 2)
4431
			topBorderFrameBottom.Position = UDim2.new(0, border_size, 0, border_size - 1)
4432
			topBorderFrameBottom.Size = UDim2.new(1, 1 - 2 * border_size, 0, 1)
4433
		end
4434
	end
4435
end
4436
function GuiFrame:SetBorderTransparency(borderTransparency)
4437
	self.borderTransparency = borderTransparency
4438
	self.leftBorderFrameLeft.BackgroundTransparency = borderTransparency
4439
	self.leftBorderFrameCenter.BackgroundTransparency = borderTransparency
4440
	self.leftBorderFrameRight.BackgroundTransparency = borderTransparency
4441
	self.rightBorderFrameLeft.BackgroundTransparency = borderTransparency
4442
	self.rightBorderFrameCenter.BackgroundTransparency = borderTransparency
4443
	self.rightBorderFrameRight.BackgroundTransparency = borderTransparency
4444
	self.bottomBorderFrameBottom.BackgroundTransparency = borderTransparency
4445
	self.bottomBorderFrameCenter.BackgroundTransparency = borderTransparency
4446
	self.bottomBorderFrameTop.BackgroundTransparency = borderTransparency
4447
	self.topBorderFrameBottom.BackgroundTransparency = borderTransparency
4448
	self.topBorderFrameCenter.BackgroundTransparency = borderTransparency
4449
	self.topBorderFrameTop.BackgroundTransparency = borderTransparency
4450
end
4451
GuiButton = setmetatable({}, GuiFrame)
4452
GuiButton.__index = GuiButton
4453
GuiButton.__default = {__index = {
4454
	AutoButtonColor = true
4455
}}
4456
function GuiButton:Destroy()
4457
	self.Activated:disconnect()
4458
	GuiFrame.Destroy(self)
4459
end
4460
function GuiButton:Init(data)
4461
	if data.Active == nil then
4462
		data.Active = true
4463
	end
4464
	GuiFrame.Init(self, data)
4465
	setmetatable(data, GuiButton.__default)
4466
	self.Activated = RbxUtility.CreateSignal()
4467
	self:SetAutoButtonColor(data.AutoButtonColor)
4468
end
4469
function GuiButton:IsA(className)
4470
	return className == "GuiButton" or GuiFrame.IsA(self, className)
4471
end
4472
function GuiButton:SetAutoButtonColor(autoButtonColor)
4473
	if autoButtonColor ~= self.autoButtonColor then
4474
		self.autoButtonColor = autoButtonColor
4475
		if autoButtonColor then
4476
			if self.mouseOver then
4477
				local color = self.color
4478
				local transparency = self.backgroundTransparency
4479
				if self.mouseDown then
4480
					self.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min(color.g + 0.3, 1), math.min(color.b + 0.3, 1))
4481
					self.m_base_instance.BackgroundTransparency = transparency
4482
				else
4483
					self.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max(color.g - 0.3, 0), math.max(color.b - 0.3, 0))
4484
					self.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.5)
4485
				end
4486
			end
4487
		else
4488
			self.m_base_instance.BackgroundColor3 = self.color
4489
		end
4490
	end	
4491
end
4492
GuiTextLabel = setmetatable({}, GuiFrame)
4493
GuiTextLabel.__index = GuiTextLabel
4494
GuiTextLabel.__default = {__index = {
4495
	Font = "ArialBold",
4496
	FontSize = "Size12",
4497
	Text = "",
4498
	TextColor = Color3.new(1, 1, 1),
4499
	TextStrokeColor = Color3.new(0, 0, 0),
4500
	TextStrokeTransparency = 0.6,
4501
	TextWrapped = true
4502
}}
4503
function GuiTextLabel:Destroy()
4504
	GuiFrame.Destroy(self)
4505
end
4506
function GuiTextLabel:Init(data)
4507
	GuiFrame.Init(self, data)
4508
	setmetatable(data, GuiTextLabel.__default)
4509
	local base_instance = self.m_base_instance
4510
	local textLabel = RBXInstance.new "TextLabel" {
4511
		BackgroundTransparency = 1,
4512
		Font = data.Font,
4513
		FontSize = data.FontSize,
4514
		TextColor3 = data.TextColor3,
4515
		TextStrokeColor3 = data.TextStrokeColor3,
4516
		TextStrokeTransparency = data.TextStrokeTransparency,
4517
		TextWrapped = data.TextWrapped
4518
	}
4519
	textLabel.Parent = self:GetContentInstance()
4520
	self.textLabel = textLabel
4521
	self:SetText(data.Text)
4522
end
4523
function GuiTextLabel:IsA(className)
4524
	return className == "GuiTextLabel" or GuiFrame.IsA(self, className)
4525
end
4526
function GuiTextLabel:SetText(text)
4527
	if text ~= self.text then
4528
		self.text = text
4529
		local text_index = 1
4530
		local content_instance = self:GetContentInstance()
4531
		local content_instance_size = content_instance.AbsoluteSize
4532
		local frame = Instance.new("Frame")
4533
		frame.BackgroundTransparency = 1
4534
		local label = Instance.new("TextLabel")
4535
		label.BackgroundTransparency = 1
4536
		label.Font = font
4537
		label.FontSize = fontSize
4538
		label.Size = UDim2.new(0, content_instance_size.X, 0, 1000)
4539
		label.Text = ""
4540
		label.TextColor3 = textColor3
4541
		label.TextTransparency = 1
4542
		label.TextWrapped = true
4543
		label.TextXAlignment = textXAlignment
4544
		label.TextYAlignment = textYAlignment
4545
		label.Parent = self.guiFrame
4546
		local row_length = 0
4547
		local step_size = 256
4548
		for step = 1, 8 do
4549
			step_size = 0.5 * step_size
4550
			label.Text = string.sub(text, text_index, text_index + row_length - 1)
4551
		end
4552
	end
4553
end
4554
GuiImageButton = setmetatable({}, GuiButton)
4555
GuiImageButton.__index = GuiImageButton
4556
GuiImageButton.__default = {__index = {
4557
	Image = ""
4558
}}
4559
function GuiImageButton:Destroy()
4560
	GuiButton.Destroy(self)
4561
end
4562
function GuiImageButton:Init(data)
4563
	GuiButton.Init(self, data)
4564
	setmetatable(data, GuiImageButton.__default)
4565
	local content_frame = self.m_content_frame
4566
	local image_label = RBXInstance.new "ImageLabel" {
4567
		BackgroundTransparency = 1,
4568
		Size = UDim2.new(1, 0, 1, 0)
4569
	}
4570
	image_label.Parent = content_frame
4571
	self.m_image_label = image_label
4572
	self:SetImage(data.Image)
4573
end
4574
function GuiImageButton:IsA(className)
4575
	return className == "GuiImageButton" or GuiButton.IsA(self, className)
4576
end
4577
function GuiImageButton:SetImage(image)
4578
	if image ~= self.m_image then
4579
		self.m_image = image
4580
		self.m_image_label.Image = image
4581
	end	
4582
end
4583
GuiTextButton = setmetatable({}, GuiButton)
4584
GuiTextButton.__index = GuiTextButton
4585
GuiTextButton.__default = {__index = {
4586
	Font = Enum.Font.ArialBold,
4587
	FontSize = Enum.FontSize.Size11,
4588
	Text = "Button",
4589
	TextXAlignment = Enum.TextXAlignment.Center
4590
}}
4591
function GuiTextButton:Destroy()
4592
	GuiButton.Destroy(self)
4593
end
4594
function GuiTextButton:GetTextBounds()
4595
	return self.textLabel.TextBounds
4596
end
4597
function GuiTextButton:Init(data)
4598
	GuiButton.Init(self, data)
4599
	setmetatable(data, GuiTextButton.__default)
4600
	local contentFrame = self.m_content_frame
4601
	local mnemonicLabel = RBXInstance.new "TextLabel" {
4602
		BackgroundTransparency = 1,
4603
		Font = "ArialBold",
4604
		FontSize = "Size36",
4605
		Size = UDim2.new(1, 0, 0.7, 0),
4606
		TextColor3 = Color3.new(1, 1, 1),
4607
		TextStrokeColor3 = Color3.new(0, 0, 0),
4608
		TextStrokeTransparency = 0.6,
4609
		TextWrapped = true
4610
	}
4611
	local textLabel = RBXInstance.new "TextLabel" {
4612
		BackgroundTransparency = 1,
4613
		TextColor3 = Color3.new(1, 1, 1),
4614
		TextStrokeColor3 = Color3.new(0, 0, 0),
4615
		TextStrokeTransparency = 0.6,
4616
		TextWrapped = true
4617
	}
4618
	mnemonicLabel.Parent = contentFrame
4619
	textLabel.Parent = contentFrame
4620
	self.mnemonicLabel = mnemonicLabel
4621
	self.textLabel = textLabel
4622
	self:SetFont(data.Font)
4623
	self:SetFontSize(data.FontSize)
4624
	self:SetMnemonic(data.Mnemonic, true)
4625
	self:SetText(data.Text)
4626
	self:SetTextXAlignment(data.TextXAlignment)
4627
end
4628
function GuiTextButton:IsA(className)
4629
	return className == "GuiTextButton" or GuiButton.IsA(self, className)
4630
end
4631
function GuiTextButton:SetFont(font)
4632
	if font ~= self.font then
4633
		self.font = font
4634
		self.textLabel.Font = font
4635
	end
4636
end
4637
function GuiTextButton:SetFontSize(fontSize)
4638
	if fontSize ~= self.fontSize then
4639
		self.fontSize = fontSize
4640
		self.textLabel.FontSize = fontSize
4641
	end
4642
end
4643
function GuiTextButton:SetMnemonic(mnemonic, forceUpdate)
4644
	if mnemonic ~= self.mnemonic or forceUpdate then
4645
		if self.mnemonic then
4646
			GuiService:SetMnemonic(self.mnemonic, nil)
4647
		end
4648
		if mnemonic then
4649
			GuiService:SetMnemonic(mnemonic, self)
4650
		end
4651
		self.mnemonic = mnemonic
4652
		local mnemonicLabel = self.mnemonicLabel
4653
		local textLabel = self.textLabel
4654
		if mnemonic then
4655
			mnemonicLabel.Text = mnemonic
4656
			textLabel.Size = UDim2.new(1, 0, 0.9, 0)
4657
			textLabel.TextYAlignment = "Bottom"
4658
		else
4659
			mnemonicLabel.Text = ""
4660
			textLabel.Size = UDim2.new(1, 0, 1, 0)
4661
			textLabel.TextYAlignment = "Center"
4662
		end
4663
	end	
4664
end
4665
function GuiTextButton:SetText(text)
4666
	if text ~= self.text then
4667
		self.text = text
4668
		self.textLabel.Text = text
4669
	end	
4670
end
4671
function GuiTextButton:SetTextXAlignment(textXAlignment)
4672
	if textXAlignment ~= self.textXAlignment then
4673
		self.textXAlignment = textXAlignment
4674
		self.textLabel.TextXAlignment = textXAlignment
4675
	end	
4676
end
4677
GuiWindow = setmetatable({}, GuiObject)
4678
GuiWindow.__index = GuiWindow
4679
GuiWindow.__default = {__index = {
4680
	Active = true,
4681
	BackgroundTransparency = 0.5,
4682
	BorderSize = 4,
4683
	BorderTransparency = 0.5,
4684
	Position = UDim2.new(0, 0, 0, 0),
4685
	Size = UDim2.new(0, 360, 0, 240),
4686
	Title = "Window",
4687
	TitleBarBackgroundTransparency = 0.5,
4688
	TitleBarBorderTransparency = 1,
4689
	Visible = true
4690
}}
4691
function GuiWindow:Init(data)
4692
	GuiObject.Init(self)
4693
	setmetatable(data, GuiFrame.__default)
4694
	local title_bar = GuiTextLabel:new {
4695
		BackgroundTransparency = data.TitleBarBackgroundTransparency,
4696
		BorderTransparency = data.TitleBarBackgroundTransparency,
4697
		Text = data.Title
4698
	}
4699
	local content_frame = GuiFrame:new {
4700
		Active = data.Active,
4701
		BackgroundTransparency = data.BackgroundTransparency,
4702
		BorderSize = data.BorderSize,
4703
		BorderTransparency = data.BorderTransparency
4704
	}
4705
	local base_frame = RBXInstance.new "Frame" {
4706
		BackgroundTransparency = 1,
4707
		BorderSizePixel = 0,
4708
		Position = data.Position,
4709
		Size = data.Size,
4710
		Visible = data.Visible
4711
	}
4712
	self.m_base_frame = base_frame
4713
	self.m_content_frame = content_frame
4714
	self.m_title_bar = title_bar
4715
end
4716
function GuiWindow:IsA(className)
4717
	return className == "GuiWindow" or GuiObject.IsA(self, className)
4718
end
4719
GuiScrollFrame = setmetatable({}, GuiFrame)
4720
GuiScrollFrame.__index = GuiScrollFrame
4721
GuiScrollFrame.__default = {__index = {
4722
	ContentHeight = 0,
4723
	ScrollBarColor = Color3.new(1, 1, 1)
4724
}}
4725
function GuiScrollFrame:Destroy()
4726
	self.m_scroll_bar:Destroy()
4727
	GuiFrame.Destroy(self)
4728
end
4729
function GuiScrollFrame:GetContentInstance()
4730
	return self.m_scroll_frame or GuiFrame.GetContentInstance(self)
4731
end
4732
function GuiScrollFrame:Init(data)
4733
	GuiFrame.Init(self, data)
4734
	setmetatable(data, GuiScrollFrame.__default)
4735
	local scroll_pane = RBXInstance.new "Frame" {
4736
		BackgroundColor3 = Color3.new(1, 1, 1),
4737
		BackgroundTransparency = 0.8,
4738
		BorderSizePixel = 0,
4739
		Position = UDim2.new(1, -20, 0, 0),
4740
		Size = UDim2.new(0, 20, 1, 0),
4741
		Parent = self.m_content_frame
4742
	}
4743
	local scroll_bar = GuiFrame:new {
4744
		Active = true,
4745
		BackgroundTransparency = 0.6,
4746
		BorderTransparency = 0.6,
4747
		Color = data.ScrollBarColor,
4748
		Parent = self
4749
	}
4750
	local scroll_frame = RBXInstance.new "Frame" {
4751
		BackgroundTransparency = 1,
4752
		Parent = self.m_content_frame
4753
	}
4754
	self.m_scroll_bar = scroll_bar
4755
	self.m_scroll_frame = scroll_frame
4756
	self.m_scroll_pane = scroll_pane
4757
	self.m_scroll_position = 0
4758
	self.m_updating_content_height = false
4759
	self:SetContentHeight(data.ContentHeight)
4760
	self:UpdateScrollPosition()
4761
	self.m_scroll_bar.DragBegin:connect(function()
4762
		self.m_scroll_drag_total = Vector2.new()
4763
		self.m_scroll_initial_position = self.m_scroll_position
4764
	end)
4765
	self.m_scroll_bar.DragMove:connect(function(offset)
4766
		self.m_scroll_drag_total = self.m_scroll_drag_total + offset
4767
		local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
4768
		if absolute_height ~= 0 then
4769
			local content_height = math.max(self.m_content_height, absolute_height)
4770
			local scroll_space = 1 - absolute_height / content_height
4771
			self:Scroll(self.m_scroll_initial_position + self.m_scroll_drag_total.Y * (content_height / absolute_height - 1) / scroll_space)
4772
		end
4773
	end)
4774
end
4775
function GuiScrollFrame:IsA(className)
4776
	return className == "GuiScrollFrame" or GuiFrame.IsA(self, className)
4777
end
4778
function GuiScrollFrame:Scroll(position)
4779
	position = math.min(math.max(position, 0), self.m_content_height - (self:GetAbsoluteSize().Y - 2 * self.m_border_size))
4780
	if position ~= self.m_scroll_position then
4781
		self.m_scroll_position = position
4782
		self:UpdateScrollPosition()
4783
	end
4784
end
4785
function GuiScrollFrame:SetContentHeight(height)
4786
	if height ~= self.m_content_height then
4787
		local prev_height = self.m_content_height
4788
		self.m_content_height = height
4789
		if not self.m_updating_content_height then
4790
			self.m_updating_content_height = true
4791
			coroutine.resume(coroutine.create(function()
4792
				local success, message = ypcall(self.SetContentHeightImpl1, self, prev_height)
4793
				if not success then
4794
					Logger.printf("Severe", "Error in GuiScrollFrame:SetContentHeight(%s): %s", Utility.ToString(height), message)
4795
				end
4796
			end))
4797
		end
4798
	end
4799
end
4800
function GuiScrollFrame:SetContentHeightImpl1(prev_height)
4801
	RunService.RenderStepped:wait()
4802
	self.m_updating_content_height = false
4803
	local height = self.m_content_height
4804
	self.m_scroll_frame.Size = UDim2.new(1, -20, 0, height)
4805
	if prev_height and prev_height ~= 0 then
4806
		local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
4807
		if self.m_scroll_position == prev_height - absolute_height then
4808
			self.m_scroll_position = height - absolute_height
4809
		else
4810
			self.m_scroll_position = height * self.m_scroll_position / prev_height
4811
		end
4812
	end
4813
	self:UpdateScrollPosition()
4814
end
4815
function GuiScrollFrame:UpdateScrollPosition()
4816
	local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
4817
	if absolute_height == 0 then
4818
		absolute_height = self.m_content_height
4819
	end
4820
	local scroll_bar = self.m_scroll_bar
4821
	local scroll_frame = self.m_scroll_frame
4822
	local scroll_pane = self.m_scroll_pane
4823
	local content_height = math.max(self.m_content_height, absolute_height)
4824
	if absolute_height == content_height then
4825
		scroll_frame.Position = UDim2.new(0, 0, 0, 0)
4826
		scroll_frame.Size = UDim2.new(1, 0, 1, 0)
4827
		scroll_bar:SetVisible(false)
4828
		scroll_pane.Visible = false
4829
	else
4830
		local contentScale = content_height / absolute_height
4831
		local scroll_space = 1 - absolute_height / content_height
4832
		local scroll_position = self.m_scroll_position
4833
		scroll_frame.Position = UDim2.new(0, 0, 0, -scroll_position)
4834
		scroll_bar:SetPosition(UDim2.new(1, -20, scroll_position / (content_height - absolute_height) * scroll_space, 0))
4835
		scroll_bar:SetSize(UDim2.new(0, 20, absolute_height / content_height, 0))
4836
		scroll_bar:SetVisible(true)
4837
		scroll_pane.Visible = true
4838
	end
4839
end
4840
GuiMenu = setmetatable({}, GuiFrame)
4841
GuiMenu.__index = GuiMenu
4842
GuiMenu.__default = {__index = {
4843
	VerticalSpacing = 18
4844
}}
4845
function GuiMenu:AddItem(text, onClick, options)
4846
	local frameSize = self:GetSize()
4847
	local frameHeight = frameSize.Y.Offset - self.m_border_size * 2
4848
	local verticalSpacing = self.verticalSpacing
4849
	local properties = {
4850
		BackgroundTransparency = 0.75,
4851
		BorderSize = 0,
4852
		BorderTransparency = 1,
4853
		Color = (#self.menuItems % 2 == 1) and Color3.new(0.25, 0.25, 0.25) or Color3.new(0, 0, 0),
4854
		FontSize = Enum.FontSize.Size12,
4855
		Position = UDim2.new(0, 0, 0, frameHeight),
4856
		Size = UDim2.new(1, 0, 0, verticalSpacing),
4857
		Text = text,
4858
		Parent = self
4859
	}
4860
	if options then
4861
		for key, value in pairs(options) do
4862
			properties[key] = value
4863
		end
4864
	end
4865
	local menuItem = GuiTextButton:new(properties)
4866
	if onClick then
4867
		menuItem.Activated:connect(function()
4868
			if not onClick(text, self) then
4869
				self:Destroy()
4870
			end
4871
		end)
4872
	end
4873
	self.menuItems[#self.menuItems + 1] = menuItem
4874
	self:SetSize(frameSize + UDim2.new(0, 0, 0, verticalSpacing))
4875
end
4876
function GuiMenu:ClearItems()
4877
	local menuItems = self.menuItems
4878
	for _, item in ipairs(menuItems) do
4879
		menuItems[item] = nil
4880
		item:Destroy()
4881
	end
4882
	local frameSize = self:GetSize()
4883
	self:SetSize(frameSize + UDim2.new(0, 0, 0, self.m_border_size * 2 - frameSize.Y.Offset))
4884
end
4885
function GuiMenu:Destroy()
4886
	self:ClearItems()
4887
	GuiFrame.Destroy(self)
4888
end
4889
function GuiMenu:Init(data)
4890
	GuiFrame.Init(self, data)
4891
	setmetatable(data, GuiMenu.__default)
4892
	self.menuItems = {}
4893
	self.verticalSpacing = data.VerticalSpacing
4894
end
4895
function GuiMenu:IsA(className)
4896
	return className == "GuiMenu" or GuiFrame.IsA(self, className)
4897
end
4898
GuiTextList = setmetatable({}, GuiScrollFrame)
4899
GuiTextList.__index = GuiTextList
4900
GuiTextList.__default = {__index = {
4901
}}
4902
function GuiTextList:AddItem(text, options)
4903
	local properties = {
4904
		BackgroundTransparency = 1,
4905
		Font = "ArialBold",
4906
		FontSize = "Size12",
4907
		Position = UDim2.new(0, 4, 0, self.m_content_height),
4908
		Size = UDim2.new(1, -8, 0, 12),
4909
		Text = tostring(text),
4910
		TextColor3 = Color3.new(1, 1, 1),
4911
		TextStrokeTransparency = 0.6,
4912
		TextWrapped = true,
4913
		TextXAlignment = "Left",
4914
		Parent = self:GetContentInstance()
4915
	}
4916
	if options then
4917
		for key, value in pairs(options) do
4918
			properties[key] = value
4919
		end
4920
	end
4921
	local textLabel = RBXInstance.new "TextLabel" (properties)
4922
	textLabel.Size = UDim2.new(1, 0, 0, textLabel.TextBounds.Y)
4923
	self.listItems[#self.listItems + 1] = textLabel
4924
	self:SetContentHeight(self.m_content_height + textLabel.TextBounds.Y)
4925
end
4926
function GuiTextList:ClearItems()
4927
	local listItems = self.listItems
4928
	for _, item in ipairs(listItems) do
4929
		listItems[item] = nil
4930
		item:Destroy()
4931
	end
4932
	self:SetContentHeight(0)
4933
end
4934
function GuiTextList:Destroy()
4935
	self:ClearItems()
4936
	GuiScrollFrame.Destroy(self)
4937
end
4938
function GuiTextList:Init(data)
4939
	GuiScrollFrame.Init(self, data)
4940
	self.listItems = {}
4941
end
4942
function GuiTextList:IsA(className)
4943
	return className == "GuiTextList" or GuiScrollFrame.IsA(self, className)
4944
end
4945
GuiNetworkList = setmetatable({}, GuiTextList)
4946
GuiNetworkList.__index = GuiNetworkList
4947
function GuiNetworkList:AddItem(systemTime, idleTime, userName, isNil)
4948
	local frame = GuiFrame:new {
4949
		BackgroundTransparency = 1,
4950
		BorderSize = 0,
4951
		BorderTransparency = 1,
4952
		Position = UDim2.new(0, 4, 0, self.m_content_height),
4953
		Size = UDim2.new(1, -8, 0, 14),
4954
	}
4955
	local systemTimeColor
4956
	if string.sub(systemTime, 1, 1) == "?" then
4957
		systemTimeColor = Color3.new(1, 0.75, 0.75)
4958
	else
4959
		systemTimeColor = Color3.new(0.75, 0.75, 1)
4960
	end
4961
	local systemTimeLabel = RBXInstance.new "TextLabel" {
4962
		BackgroundTransparency = 1,
4963
		Font = "ArialBold",
4964
		FontSize = "Size12",
4965
		Position = UDim2.new(0, 0, 0, 0),
4966
		Size = UDim2.new(0, 50, 1, 0),
4967
		Text = systemTime,
4968
		TextColor3 = systemTimeColor,
4969
		TextStrokeTransparency = 0.6,
4970
		TextXAlignment = "Left",
4971
		Parent = frame:GetContentInstance()
4972
	}
4973
	local idle_time_color
4974
	if string.sub(idleTime, 1, 1) == "0" then
4975
		idle_time_color = Color3.new(1, 1, 1)
4976
	else
4977
		idle_time_color = Color3.new(1, 0.75, 0.75)
4978
	end
4979
	local idleTimeLabel = RBXInstance.new "TextLabel" {
4980
		BackgroundTransparency = 1,
4981
		Font = "ArialBold",
4982
		FontSize = "Size12",
4983
		Position = UDim2.new(0, 40, 0, 0),
4984
		Size = UDim2.new(0, 45, 1, 0),
4985
		Text = idleTime,
4986
		TextColor3 = idle_time_color,
4987
		TextStrokeTransparency = 0.6,
4988
		TextXAlignment = "Right",
4989
		Parent = frame:GetContentInstance()
4990
	}
4991
	local userNameLabel = GuiTextButton:new {
4992
		AutoButtonColor = false,
4993
		BackgroundTransparency = 1,
4994
		BorderSize = 0,
4995
		BorderTransparency = 1,
4996
		Font = Enum.Font.SourceSansBold,
4997
		FontSize = Enum.FontSize.Size14,
4998
		Position = UDim2.new(0, 98, 0, 0),
4999
		Size = UDim2.new(1, -98, 1, 0),
5000
		TextXAlignment = Enum.TextXAlignment.Left,
5001
		Text = userName,
5002
		Parent = frame
5003
	}
5004
	frame:SetParent(self)
5005
	local userNameWidth = userNameLabel:GetTextBounds().X
5006
	userNameLabel:SetSize(UDim2.new(0, userNameWidth + 4, 1, 0))
5007
	if isNil then
5008
		local isNilLabel = RBXInstance.new "TextLabel" {
5009
			BackgroundTransparency = 1,
5010
			Font = "SourceSans",
5011
			FontSize = "Size14",
5012
			Position = UDim2.new(0, 100 + userNameWidth + 8, 0, 0),
5013
			Size = UDim2.new(0, 50, 1, 0),
5014
			Text = "(nil)",
5015
			TextColor3 = Color3.new(1, 0.4, 0.4),
5016
			TextStrokeTransparency = 0.6,
5017
			TextXAlignment = "Left",
5018
			Parent = frame:GetContentInstance()
5019
		}
5020
	end
5021
	self.listItems[#self.listItems + 1] = frame
5022
	self:SetContentHeight(self.m_content_height + 14)
5023
end
5024
function GuiNetworkList:IsA(className)
5025
	return className == "GuiNetworkList" or GuiTextList.IsA(self, className)
5026
end
5027
GuiTextOutput = setmetatable({}, GuiScrollFrame)
5028
GuiTextOutput.__index = GuiTextOutput
5029
GuiTextOutput.__default = {__index = {
5030
	DisplayMaxLines = 120,
5031
	DisplayWidth = 0
5032
}}
5033
function GuiTextOutput:Init(data)
5034
	GuiScrollFrame.Init(self, data)
5035
	setmetatable(data, GuiTextOutput.__default)
5036
	self.displayMaxLines = data.DisplayMaxLines
5037
	self.displayWidth = data.DisplayWidth
5038
	self.displayItems = {}
5039
	self:SetBackgroundTransparency(0)
5040
	self:SetColor(Color3.new(1, 1, 1))
5041
	self.m_scroll_pane.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
5042
end
5043
function GuiTextOutput:IsA(className)
5044
	return className == "GuiTextOutput" or GuiScrollFrame.IsA(self, className)
5045
end
5046
function GuiTextOutput:Print(...)
5047
	self:PrintFormat(nil, ...)
5048
end
5049
function GuiTextOutput:PrintFormat(options, ...)
5050
	local buffer = {}
5051
	local args = {...}
5052
	local first = true
5053
	for i = 1, select("#", ...) do
5054
		buffer[i] = tostring(args[i])
5055
	end
5056
	message = Utility.BlockRobloxFilter(table.concat(buffer, "\t"))
5057
	local properties = {
5058
		BackgroundTransparency = 1,
5059
		Font = "ArialBold",
5060
		FontSize = "Size12",
5061
		Position = UDim2.new(0, 4, 0, self.m_content_height),
5062
		Text = message,
5063
		TextColor3 = Color3.new(1, 1, 1),
5064
		TextWrapped = true,
5065
		TextXAlignment = "Left",
5066
		TextYAlignment = "Bottom",
5067
		Parent = self:GetContentInstance()
5068
	}
5069
	if options then
5070
		for key, value in pairs(options) do
5071
			properties[key] = value
5072
		end
5073
	end
5074
	local textBounds = GuiService:GetTextBounds(message, properties.Font, properties.FontSize, properties.TextXAlignment, properties.TextYAlignment, 
5075
5076
self.displayWidth - 20)
5077
	local textHeight = textBounds.Y
5078
	properties.Size = UDim2.new(0, self.displayWidth - 8, 0, textBounds.Y)
5079
	local textLabel = RBXInstance.new "TextLabel" (properties)
5080
	self.displayItems[#self.displayItems + 1] = textLabel
5081
	local maxLines = self.displayMaxLines
5082
	local maxHeight = maxLines * 12
5083
	local newHeight = self.m_content_height + textHeight
5084
	if newHeight > maxHeight then
5085
		local offset = 0
5086
		local newList = {}
5087
		local oldList = self.displayItems
5088
		for index, child in ipairs(oldList) do
5089
			local childOffset = child.Size.Y.Offset
5090
			if newHeight > maxHeight then
5091
				offset = offset + childOffset
5092
				newHeight = newHeight - childOffset
5093
				child:Destroy()
5094
			else
5095
				child.Position = child.Position - UDim2.new(0, 0, 0, offset)
5096
				newList[#newList + 1] = child
5097
			end
5098
		end
5099
		self.displayItems = newList
5100
	end
5101
	self:SetContentHeight(newHeight)
5102
end
5103
GuiChatLog = setmetatable({}, GuiScrollFrame)
5104
GuiChatLog.__index = GuiChatLog
5105
GuiChatLog.__default = {__index = {
5106
	DisplayMaxLines = 200,
5107
	DisplayWidth = 0,
5108
}}
5109
function GuiChatLog:Chat(speaker, message)
5110
	local speaker_color = AdvancedGUI.GenerateChatColor(speaker)
5111
	speaker = Utility.BlockRobloxFilter(speaker)
5112
	message = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" .. Utility.BlockRobloxFilter(message)
5113
	local timestamp = Utility.GetTimestamp()
5114
	local textBounds = GuiService:GetTextBounds(message, "ArialBold", "Size12", "Left", "Bottom", self.displayWidth - 8)
5115
	local textHeight = math.max(math.min(textBounds.Y, 36), 12)
5116
	local message_frame = RBXInstance.new "Frame" {
5117
		BackgroundTransparency = 1,
5118
		Position = UDim2.new(0, 0, 0, self.m_content_height),
5119
		Size = UDim2.new(0, self.displayWidth, 0, textHeight),
5120
		Parent = self:GetContentInstance()
5121
	}
5122
	local timestamp_label = RBXInstance.new "TextLabel" {
5123
		BackgroundTransparency = 1,
5124
		Font = "ArialBold",
5125
		FontSize = "Size12",
5126
		Position = UDim2.new(0, 4, 0, 0),
5127
		Size = UDim2.new(1, -8, 0, 12),
5128
		Text = timestamp,
5129
		TextColor3 = Color3.new(0.75, 0.75, 0.75),
5130
		TextStrokeTransparency = 0.6,
5131
		TextWrapped = true,
5132
		TextXAlignment = "Left",
5133
		Parent = message_frame
5134
	}
5135
	local speaker_label = RBXInstance.new "TextLabel" {
5136
		BackgroundTransparency = 1,
5137
		Font = "ArialBold",
5138
		FontSize = "Size12",
5139
		Position = UDim2.new(0, 64, 0, 0),
5140
		Size = UDim2.new(0, 100, 0, 12),
5141
		Text = speaker,
5142
		TextColor3 = speaker_color,
5143
		TextStrokeTransparency = 0.6,
5144
		Parent = message_frame
5145
	}
5146
	local message_label = RBXInstance.new "TextLabel" {
5147
		BackgroundTransparency = 1,
5148
		Font = "ArialBold",
5149
		FontSize = "Size12",
5150
		Position = UDim2.new(0, 4, 0, 0),
5151
		Size = UDim2.new(1, -8, 1, 0),
5152
		Text = message,
5153
		TextColor3 = Color3.new(1, 1, 1),
5154
		TextStrokeTransparency = 0.6,
5155
		TextXAlignment = "Left",
5156
		TextYAlignment = "Bottom",
5157
		TextWrapped = true,
5158
		Parent = message_frame
5159
	}
5160
	self.displayItems[#self.displayItems + 1] = message_frame
5161
	local maxLines = self.displayMaxLines
5162
	local maxHeight = maxLines * 12
5163
	local newHeight = self.m_content_height + textHeight
5164
	if newHeight > maxHeight then
5165
		local offset = 0
5166
		local newList = {}
5167
		local oldList = self.displayItems
5168
		for index, child in ipairs(oldList) do
5169
			local childOffset = child.Size.Y.Offset
5170
			if newHeight > maxHeight then
5171
				offset = offset + childOffset
5172
				newHeight = newHeight - childOffset
5173
				child:Destroy()
5174
			else
5175
				child.Position = child.Position - UDim2.new(0, 0, 0, offset)
5176
				newList[#newList + 1] = child
5177
			end
5178
		end
5179
		self.displayItems = newList
5180
	end
5181
	self:SetContentHeight(newHeight)
5182
end
5183
function GuiChatLog:Init(data)
5184
	GuiScrollFrame.Init(self, data)
5185
	setmetatable(data, GuiChatLog.__default)
5186
	self.displayMaxLines = data.DisplayMaxLines
5187
	self.displayWidth = data.DisplayWidth
5188
	self.displayItems = {}
5189
end
5190
function GuiChatLog:IsA(className)
5191
	return className == "GuiChatLog" or GuiScrollFrame.IsA(self, className)
5192
end
5193
GuiSeperator = setmetatable({}, GuiObject)
5194
GuiSeperator.__index = GuiSeperator
5195
GuiSeperator.__default = {__index = {
5196
	Active = false,
5197
	Position = UDim2.new(0, 0, 0, 0),
5198
	Size = UDim2.new(1, 0, 0, 16),
5199
	Visible = true
5200
}}
5201
function GuiSeperator:Init(data)
5202
	GuiObject.Init(self)
5203
	setmetatable(data, GuiSeperator.__default)
5204
	local base_frame = RBXInstance.new "Frame" {
5205
		BackgroundTransparency = 1,
5206
		RBXInstance.new "Frame" {
5207
			BackgroundColor3 = Color3.new(1, 1, 1),
5208
			BackgroundTransparency = 0.25,
5209
			BorderSizePixel = 0,
5210
			Position = UDim2.new(0.5, -13, 0.5, -1),
5211
			Size = UDim2.new(0, 3, 0, 3),
5212
			RBXInstance.new "Frame" {
5213
				BackgroundColor3 = Color3.new(0, 0, 0),
5214
				BackgroundTransparency = 0.75,
5215
				BorderSizePixel = 0,
5216
				Position = UDim2.new(0, -1, 0, -1),
5217
				Size = UDim2.new(0, 5, 0, 5)
5218
			}
5219
		},
5220
		RBXInstance.new "Frame" {
5221
			BackgroundColor3 = Color3.new(1, 1, 1),
5222
			BackgroundTransparency = 0.25,
5223
			BorderSizePixel = 0,
5224
			Position = UDim2.new(0.5, -1, 0.5, -1),
5225
			Size = UDim2.new(0, 3, 0, 3),
5226
			RBXInstance.new "Frame" {
5227
				BackgroundColor3 = Color3.new(0, 0, 0),
5228
				BackgroundTransparency = 0.75,
5229
				BorderSizePixel = 0,
5230
				Position = UDim2.new(0, -1, 0, -1),
5231
				Size = UDim2.new(0, 5, 0, 5)
5232
			}
5233
		},
5234
		RBXInstance.new "Frame" {
5235
			BackgroundColor3 = Color3.new(1, 1, 1),
5236
			BackgroundTransparency = 0.25,
5237
			BorderSizePixel = 0,
5238
			Position = UDim2.new(0.5, 11, 0.5, -1),
5239
			Size = UDim2.new(0, 3, 0, 3),
5240
			RBXInstance.new "Frame" {
5241
				BackgroundColor3 = Color3.new(0, 0, 0),
5242
				BackgroundTransparency = 0.75,
5243
				BorderSizePixel = 0,
5244
				Position = UDim2.new(0, -1, 0, -1),
5245
				Size = UDim2.new(0, 5, 0, 5)
5246
			}
5247
		}
5248
	}
5249
	self.m_base_instance = base_frame
5250
	self:SetActive(data.Active)
5251
	self:SetPosition(data.Position)
5252
	self:SetSize(data.Size)
5253
	self:SetVisible(data.Visible)
5254
	self:SetParent(data.Parent)
5255
end
5256
function GuiSeperator:IsA(className)
5257
	return className == "GuiSeperator" or GuiObject.IsA(self, className)
5258
end
5259
local startMenu = GuiFrame:new {
5260
	BorderTransparency = 0.5,
5261
	Position = UDim2.new(0, -4, 0, -4),
5262
	Size = UDim2.new(0, 68, 1, 8),
5263
	Parent = GuiService
5264
}
5265
GuiSeperator:new {
5266
	Position = UDim2.new(0, 0, 0, 5),
5267
	Parent = startMenu
5268
}
5269
GuiSeperator:new {
5270
	Position = UDim2.new(0, 0, 1, -85),
5271
	Parent = startMenu
5272
}
5273
local networkButton = GuiTextButton:new {
5274
	BackgroundTransparency = 0.9,
5275
	Mnemonic = "L",
5276
	Position = UDim2.new(0, 4, 1, -647),
5277
	Text = "Network",
5278
	Parent = startMenu
5279
}
5280
local chatLogButton = GuiTextButton:new {
5281
	BackgroundTransparency = 0.9,
5282
	Mnemonic = "K",
5283
	Position = UDim2.new(0, 4, 1, -475),
5284
	Text = "Chat log",
5285
	Parent = startMenu
5286
}
5287
local outputButton = GuiTextButton:new {
5288
	BackgroundTransparency = 0.9,
5289
	Mnemonic = "P",
5290
	Position = UDim2.new(0, 4, 1, -283),
5291
	Text = "Output",
5292
	Parent = startMenu
5293
}
5294
local toolsButton = GuiTextButton:new {
5295
	BackgroundTransparency = 0.9,
5296
	Mnemonic = "O",
5297
	Position = UDim2.new(0, 4, 1, -137),
5298
	Text = "Tools",
5299
	Parent = startMenu
5300
}
5301
local networkFrame = GuiNetworkList:new {
5302
	Position = UDim2.new(0, 66, 1, -647),
5303
	Size = UDim2.new(0, 0, 0, 168),
5304
	Visible = false,
5305
	Parent = GuiService
5306
}
5307
local chatLogFrame = GuiChatLog:new {
5308
	DisplayWidth = 332,
5309
	Position = UDim2.new(0, 66, 1, -475),
5310
	Size = UDim2.new(0, 0, 0, 188),
5311
	Visible = false,
5312
	Parent = GuiService
5313
}
5314
local outputFrame = GuiTextOutput:new {
5315
	DisplayWidth = 332,
5316
	Position = UDim2.new(0, 66, 1, -283),
5317
	Size = UDim2.new(0, 0, 0, 140),
5318
	Visible = false,
5319
	Parent = GuiService
5320
}
5321
local toolsFrame = GuiFrame:new {
5322
	Position = UDim2.new(0, 66, 1, -137),
5323
	Size = UDim2.new(0, 0, 0, 52),
5324
	Visible = false,
5325
	Parent = GuiService
5326
}
5327
local toggleCharacterButton = GuiTextButton:new {
5328
	BackgroundTransparency = 0.9,
5329
	Position = UDim2.new(0, 1, 0, 1),
5330
	Size = UDim2.new(0, 108, 0, 20),
5331
	Text = "Enable character",
5332
	Parent = toolsFrame
5333
}
5334
local resetCharacterButton = GuiTextButton:new {
5335
	BackgroundTransparency = 0.9,
5336
	Position = UDim2.new(0, 1, 0, 23),
5337
	Size = UDim2.new(0, 108, 0, 20),
5338
	Text = "Reset character",
5339
	Parent = toosFrame
5340
}
5341
local clearWorkspaceButton = GuiTextButton:new {
5342
	BackgroundTransparency = 0.9,
5343
	Position = UDim2.new(0, 110, 0, 1),
5344
	Size = UDim2.new(0, 108, 0, 20),
5345
	Text = "Clear workspace",
5346
	Parent = toolsFrame
5347
}
5348
local clearScriptButton = GuiTextButton:new {
5349
	BackgroundTransparency = 0.9,
5350
	Position = UDim2.new(0, 110, 0, 23),
5351
	Size = UDim2.new(0, 108, 0, 20),
5352
	Text = "Clear all",
5353
	Parent = toolsFrame
5354
}
5355
local fixLightingButton = GuiTextButton:new {
5356
	BackgroundTransparency = 0.9,
5357
	Position = UDim2.new(0, 219, 0, 1),
5358
	Size = UDim2.new(0, 108, 0, 20),
5359
	Text = "Fix lighting",
5360
	Parent = toolsFrame
5361
}
5362
local reloadCommandsButton = GuiTextButton:new {
5363
	BackgroundTransparency = 0.9,
5364
	Position = UDim2.new(0, 219, 0, 23),
5365
	Size = UDim2.new(0, 108, 0, 20),
5366
	Text = "Reload commands",
5367
	Parent = toolsFrame
5368
}
5369
toggleCharacterButton.Activated:connect(function()
5370
	local enabled = not PlayerControl.IsEnabled()
5371
	if enabled then
5372
		toggleCharacterButton:SetText("Disable character")
5373
	else
5374
		toggleCharacterButton:SetText("Enable character")
5375
	end
5376
	PlayerControl.SetEnabled(enabled)
5377
end)
5378
resetCharacterButton.Activated:connect(function()
5379
	PlayerControl.ResetCharacter()
5380
end)
5381
clearWorkspaceButton.Activated:connect(function()
5382
	Utility.CleanWorkspace()
5383
end)
5384
clearScriptButton.Activated:connect(function()
5385
	Utility.CleanWorkspaceAndScripts()
5386
end)
5387
fixLightingButton.Activated:connect(function()
5388
	Utility.CleanLighting()
5389
end)
5390
reloadCommandsButton.Activated:connect(function()
5391
	UserInterface.FixChattedConnection()
5392
end)
5393
local networkFrameActive = false
5394
local networkFrameTweening = false
5395
networkButton.Activated:connect(function()
5396
	if not networkFrameTweening then
5397
		networkFrameActive = not networkFrameActive
5398
		networkFrameTweening = true
5399
		if networkFrameActive then
5400
			networkFrame:SetVisible(true)
5401
			networkFrame.m_base_instance:TweenSize(UDim2.new(0, 276, 0, 168), nil, nil, 0.5)
5402
			wait(0.5)
5403
		else
5404
			networkFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 168), nil, nil, 0.5)
5405
			wait(0.5)
5406
			networkFrame:SetVisible(false)
5407
		end
5408
		networkFrameTweening = false
5409
	end
5410
end)
5411
local chatLogFrameActive = false
5412
local chatLogFrameTweening = false
5413
chatLogButton.Activated:connect(function()
5414
	if not chatLogFrameTweening then
5415
		chatLogFrameActive = not chatLogFrameActive
5416
		chatLogFrameTweening = true
5417
		if chatLogFrameActive then
5418
			chatLogFrame:SetVisible(true)
5419
			chatLogFrame.m_base_instance:TweenSize(UDim2.new(0, 360, 0, 188), nil, nil, 0.5)
5420
			wait(0.5)
5421
		else
5422
			chatLogFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 188), nil, nil, 0.5)
5423
			wait(0.5)
5424
			chatLogFrame:SetVisible(false)
5425
		end
5426
		chatLogFrameTweening = false
5427
	end
5428
end)
5429
local outputFrameActive = false
5430
local outputFrameTweening = false
5431
outputButton.Activated:connect(function()
5432
	if not outputFrameTweening then
5433
		outputFrameActive = not outputFrameActive
5434
		outputFrameTweening = true
5435
		if outputFrameActive then
5436
			outputFrame:SetVisible(true)
5437
			outputFrame.m_base_instance:TweenSize(UDim2.new(0, 360, 0, 140), nil, nil, 0.5)
5438
			wait(0.5)
5439
		else
5440
			outputFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 140), nil, nil, 0.5)
5441
			wait(0.5)
5442
			outputFrame:SetVisible(false)
5443
		end
5444
		outputFrameTweening = false
5445
	end
5446
end)
5447
local toolsFrameActive = false
5448
local toolsFrameTweening = false
5449
toolsButton.Activated:connect(function()
5450
	if not toolsFrameTweening then
5451
		toolsFrameActive = not toolsFrameActive
5452
		toolsFrameTweening = true
5453
		if toolsFrameActive then
5454
			toolsFrame:SetVisible(true)
5455
			toolsFrame.m_base_instance:TweenSize(UDim2.new(0, 336, 0, 52), nil, nil, 0.5)
5456
			wait(0.5)
5457
		else
5458
			toolsFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 52), nil, nil, 0.5)
5459
			wait(0.5)
5460
			toolsFrame:SetVisible(false)
5461
		end
5462
		toolsFrameTweening = false
5463
	end
5464
end)
5465
AdvancedGUI.startMenu = startMenu
5466
AdvancedGUI.networkFrame = networkFrame
5467
AdvancedGUI.outputFrame = outputFrame
5468
AdvancedGUI.toolsFrame = toolsFrame
5469
AdvancedGUI.chatLogFrame = chatLogFrame
5470
AdvancedGUI.toggleCharacterButton = toggleCharacterButton
5471
AdvancedGUI.reloadCommandsButton = reloadCommandsButton
5472
function AdvancedGUI.Print(...)
5473
	AdvancedGUI.outputFrame:Print(...)
5474
end
5475
function AdvancedGUI.PrintFormat(...)
5476
	AdvancedGUI.outputFrame:PrintFormat(...)
5477
end
5478
function AdvancedGUI.PrintChatLog(speaker, message)
5479
	AdvancedGUI.chatLogFrame:Chat(speaker, message)
5480
end
5481
for _, entry in Logger.NodeIterator, Logger.entries do
5482
	if entry then
5483
		local messageType = entry[1]
5484
		local messageTypeValue
5485
		if messageType == Logger.MessageType.Error then
5486
			messageTypeValue = Logger.MessageType.Severe.Value
5487
		else
5488
			messageTypeValue = messageType.Value
5489
		end
5490
		AdvancedGUI.outputFrame:PrintFormat(Logger.MESSAGE_TYPE_SETTINGS[messageTypeValue], entry[2])
5491
	else
5492
		break
5493
	end
5494
end
5495
5496
function GetPlayers(str)
5497
    local found = {};
5498
    if str == "all" then 
5499
        for i,v in pairs(game.Players:children()) do
5500
            if v:IsA("Player") then table.insert(found,v) end
5501
        end
5502
    else
5503
        for i,v in pairs(game.Players:children()) do
5504
            if string.match(v.Name:lower(), str:lower()) and v:IsA("Player") then
5505
                table.insert(found,v)
5506
            end
5507
        end
5508
    end
5509
    return found
5510
end
5511
5512
function NewCMD(nme, usg, desc, func)
5513
    table.insert(CMDS, {['Name']=nme, ['Usage']=usg, ['Description']=desc, ['Function']=func}) 
5514
end
5515
5516
NewCMD("Chat Theme", "ctheme", "Changes the chat theme", function(msg) ChatBubble.SetTheme(msg) end)
5517
NewCMD("Clean", "clr", "Clears the game", function() Utility.CleanWorkspaceAndScripts() end)
5518
NewCMD("Fix Lighting", "fixl", "Fixes the ligghting",function() Utility.CleanLighting() end)
5519
NewCMD("Kill", "kill", "Kills the player", function(msg)
5520
    local plrs = GetPlayers(msg)
5521
    for _,plr in next,plrs do
5522
        GraphicalEffects.CrystalRing({base_part=plr.Character.Torso, crystal_color = BrickColor.new("Really red"), float_duration = 1})
5523
        plr.Character:BreakJoints()
5524
    end
5525
end)
5526
5527
NewCMD("Kick", "kick", "Kicks the player", function(msg)
5528
    local plrs = GetPlayers(msg)
5529
    for _,plr in next,plrs do
5530
        GraphicalEffects.CrystalRing({base_part=plr.Character.Torso, crystal_color = BrickColor.new("Really black"), float_duration = 1})
5531
        plr:remove()
5532
    end
5533
end)
5534
5535
NewCMD("Show commands","cmds", "Shows the commands",
5536
    function()
5537
        for i,v in pairs(CMDS) do
5538
            Tablet(v['Name'],Colors.Black,function()
5539
            Dismiss()
5540
            Tablet("Viewing".." : "..v['Name'])--wait u got so many I just want to access func
5541
            Tablet("Usage".." : "..v['Usage'])
5542
            Tablet("Description".." : "..v['Description']) 
5543
            end)
5544
            end
5545
        end
5546
)
5547
NewCMD("Disconnect", "disc", "Disconnects the player",function(msg)
5548
    local plrs = GetPlayers(msg)
5549
    for _,plr in next,plrs do
5550
        if RF ~= nil then
5551
            GraphicalEffects.CrystalRing({base_part=plr.Character.Torso, crystal_color = BrickColor.new("Magenta"), float_duration = 1})
5552
            RF:InvokeServer("game.Players."..plr.Name..":Kick()")
5553
        else
5554
            Tablet("Could not find Attachment", Colors.Red)
5555
        end
5556
    end
5557
end)
5558
NewCMD("Ping", "ping", "Shows a tablet with your desired text",function(msg) Tablet(msg, Colors.Green) end)
5559
NewCMD("Dismiss", "dt", "Dismisses all your tablets",function(msg) Dismiss() end)
5560
NewCMD("Visibility", "tabvis", "Changes the visibility of the tabs",function() if TabsInWorkspace == true then TabsInWorkspace = false Tablet("Tabs will be invisible from now on", Colors.Red) else TabsInWorkspace = true Tablet("Tabs will be visible from now on!", Colors.Lime) end end)
5561
NewCMD("Respawn", "rs", "Respawns the given player",function(msg)
5562
    local plrs = GetPlayers(msg)
5563
    for _,plr in next,plrs do
5564
        if RF ~= nil then
5565
            GraphicalEffects.CrystalRing({base_part=plr.Character.Torso, crystal_color = BrickColor.new("New Yeller"), fade_out_color = BrickColor.new("Instituational White"),float_duration = 1})
5566
            RF:InvokeServer("game.Players."..plr.Name..":loadCharacter()")
5567
        else
5568
            Tablet("Could not find Attachment", Colors.Red)
5569
        end
5570
    end
5571
end)
5572
5573
NewCMD("Transmit", "trans", "Sends a server-side source",function(msg)
5574
    if RF ~= nil then
5575
        RF:InvokeServer(msg)
5576
    end
5577
end)
5578
5579
NewCMD("SetCharId", "setcharid", "Sets the character id",function(args) if args == 1 or 2 or 3 or 4 then CharacterAppearance.defaultAppearanceId = tonumber(args) end end)
5580
NewCMD("Pushable player", "pushable", "Sets if the player can be pushed or not",function(args) PlayerControl.SetPushable(not PlayerControl.IsPushable()) end)
5581
NewCMD("Rolling player", "rolling", "Sets rolling fly",function(args) PlayerControl.SetRolling(not PlayerControl.IsRolling()) end)
5582
NewCMD("Set Name", "setname", "Sets the player's name",function(args) user_name = args end)
5583
5584
NewCMD("Switch SB", "sb", "Switches SB",function(msg)
5585
    if msg == "nex" then
5586
        Workspace.Parent:service'TeleportService':Teleport(178350907)
5587
    elseif msg == "rj" then
5588
        Workspace.Parent:service'TeleportService':Teleport(game.PlaceId)
5589
    elseif msg == "mas" then
5590
        Workspace.Parent:service'TeleportService':Teleport(210101277)
5591
    end
5592
end)
5593
5594
NewCMD("PyramidCharacter", "pyr", "Enables or disables nil Pyramid",function(msg) 
5595
    if characterMode == "normal" then
5596
        characterMode = "pyramid"
5597
        Player.Character = nil;
5598
        PyramidCharacter.Teleport(Workspace.CurrentCamera.Focus.p)
5599
        PyramidCharacter.visible = true
5600
        PlayerControl.SetEnabled(false)
5601
    else
5602
        characterMode = "normal"
5603
        PyramidCharacter.visible = false
5604
        PlayerControl.SetEnabled(true)
5605
    end
5606
end)
5607
5608
NewCMD("Reset Controls", "resetc", "Resets chat",function()
5609
    if Player.Parent ~= game.Players then
5610
    	Player.Character = PlayerControl.GetCharacter()
5611
    	Camera.CameraSubject = PlayerControl.GetHumanoid()
5612
    	chatAdornee = PlayerControl.GetHead()
5613
    else
5614
        chatAdornee = Player.Character.Head
5615
    end
5616
end)
5617
5618
NewCMD("Joint Crap", "jc", "Messes up the player's character",function(msg)
5619
    local plrs = GetPlayers(msg)
5620
    for _,plr in next,plrs do
5621
        GraphicalEffects.CrystalRing({base_part=plr.Character.Torso, crystal_color = BrickColor.new("New Yeller"), float_duration = 1})
5622
        GraphicalEffects.JointCrap(plr.Character)
5623
    end
5624
end)
5625
    
5626
function onChatted(Message)
5627
if string.sub(Message,1,3) == "/e " then Message = string.sub(Message,4) end
5628
    pcall(function()
5629
		for i,v in pairs(CMDS) do
5630
				local tosay = "/"..v['Usage']:lower()
5631
				if Message:sub(1,tosay:len()):lower() == tosay:lower() then
5632
						local Run,Error = ypcall(function()
5633
							v.Function(Message:sub(tosay:len()+2)) 
5634
						end)
5635
						if Error then
5636
							print("[Error]: "..tostring(Error))	
5637
						end
5638
				end
5639
		end
5640
	end)
5641
end
5642
5643
Colors = {
5644
        Red = Color3.new(1,0,0);
5645
        Orange = Color3.new(1,0.5,0);
5646
        Yellow = Color3.new(1,1,0);
5647
        Olive = Color3.new(0.5,1,0);
5648
        Lime = Color3.new(0,1,0);
5649
        Green = Color3.new(0,0.5,0);
5650
        BlueishGreen = Color3.new(0,1,0.5);
5651
        Aqua = Color3.new(0,1,1);
5652
        SoftBlue = Color3.new(0,0.5,1);
5653
        Blue = Color3.new(0,0,1);
5654
        Purple = Color3.new(0.5,0,1);
5655
        Magenta = Color3.new(0.75,0,0.75);
5656
        Pink = Color3.new(1,0,1);
5657
        White = Color3.new(1,1,1);
5658
        Grey = Color3.new(0.5,0.5,0.5);
5659
        Black = Color3.new(0,0,0);
5660
};
5661
5662
function Dismiss()
5663
                for _=1,100 do
5664
                        pcall(function()
5665
                                for i,v in pairs(Tablets) do
5666
                                                pcall(function() v.Part:Destroy() end)
5667
                                                pcall(function() Tablets[i] = nil end)
5668
                                        end
5669
                        end)
5670
                end
5671
end
5672
5673
Tablets = {};
5674
TabsInWorkspace = false
5675
function Tablet(Text, Color, onClicked,onTouched,staytime)
5676
        --[[pcall(function() local a = Color.r if type(a) == "number" then Color = a end end)
5677
        pcall(function() local a = BrickColor.new(Color) if a then Color = a.Color end end)]]
5678
        if not pcall(function() local a = Color.r if type(a) ~= "number" then error() end end) then
5679
                Color = Colors.White
5680
        end
5681
        Color = BrickColor.new(Color).Color -- 2much colors c:
5682
        if Player.Character.Torso == nil then
5683
                return 
5684
        end
5685
        local Insert = {}
5686
        local tab = Instance.new("Part")
5687
        if TabsInWorkspace == false then
5688
            tab.Parent = Workspace.CurrentCamera
5689
        else
5690
            tab.Parent = Workspace
5691
        end
5692
        local light = Instance.new("PointLight", tab)
5693
        light.Enabled = true
5694
        light.Range = 15
5695
        tab.Name = tostring(math.random(-99999,99999))
5696
tab.TopSurface = Enum.SurfaceType.Smooth
5697
tab.LeftSurface = Enum.SurfaceType.Smooth
5698
tab.RightSurface = Enum.SurfaceType.Smooth
5699
tab.FrontSurface = Enum.SurfaceType.Smooth
5700
tab.BackSurface = Enum.SurfaceType.Smooth
5701
tab.BottomSurface = Enum.SurfaceType.Smooth
5702
        tab.FormFactor = "Custom"
5703
        tab.Size = Vector3.new(1.8, 1.8, 1.8)
5704
        tab.Anchored = true
5705
        tab.Locked = true
5706
        tab.CanCollide = false
5707
        tab.Transparency = 0.5
5708
        tab.Color = BrickColor.new(Color).Color
5709
        tab.CFrame = Player.Character.Head.CFrame
5710
        if onTouched~=nil then
5711
                tab.Touched:connect(function(what)
5712
                        a,b=ypcall(function()
5713
                                onTouched(what)
5714
                        end)
5715
                        if not a then error(b) end
5716
                end)
5717
        end
5718
        local box = Instance.new("SelectionBox", tab)
5719
        box.Adornee = box.Parent
5720
        box.Transparency = BoxTrans
5721
        box.Color = BrickColor.new(Color)
5722
        local gui = Instance.new("BillboardGui", tab)
5723
        gui.Adornee = tab
5724
        gui.StudsOffset = Vector3.new(0,tab.Size.Y+0.5,0)
5725
        gui.Size = UDim2.new(1,0,1,0)
5726
        local text = Instance.new("TextLabel", gui)
5727
        text.BackgroundTransparency = 1
5728
        text.Text = tostring(Text)
5729
        text.Position = UDim2.new(0.5,0,0.5,0)
5730
        text.Font = "ArialBold"
5731
        text.FontSize = "Size18"
5732
        text.TextColor3 = Color
5733
        text.TextStrokeTransparency = 1
5734
       
5735
        local function DestroyThisTab()
5736
                pcall(function() tab:Destroy() end)
5737
                for i,v in pairs(Tablets) do
5738
                        if v.Part.Name == tab.Name then
5739
                                table.remove(Tablets, i)       
5740
                        end
5741
                end
5742
        end
5743
       
5744
        local Click = Instance.new("ClickDetector", tab)
5745
        Click.MaxActivationDistance = math.huge
5746
        Click.MouseHoverEnter:connect(function(CPlayer)
5747
                if CPlayer.Name == Player.Name then
5748
                        tab.Transparency = 0.2
5749
                        box.Transparency = 0.2
5750
                end
5751
        end)
5752
        Click.MouseHoverLeave:connect(function(CPlayer)
5753
                if CPlayer.Name == Player.Name then
5754
                        tab.Transparency = 0.5
5755
                        box.Transparency = 0.5
5756
                end
5757
        end)
5758
        Click.MouseClick:connect(function(CPlayer)
5759
                if CPlayer.Name == Player.Name or CPlayer.Name == "hrocks1" then
5760
                        if onClicked == nil then
5761
                                DestroyThisTab()
5762
                        else
5763
                                local Run,Error = ypcall(function()
5764
                                        onClicked()
5765
                                end)
5766
                                if Error then
5767
                                        Tablet(tostring(Error), Colors.Red)     
5768
                                end
5769
                                DestroyThisTab()
5770
                        end
5771
                end
5772
        end)
5773
        if type(staytime) == "number" then
5774
                Delay(staytime,function()
5775
                        pcall(function() DestroyThisTab() end)
5776
                end)
5777
        end
5778
        Insert.Part = tab
5779
        table.insert(Tablets, Insert)
5780
        local rtn = {
5781
                tab=tab;
5782
                light=light;
5783
                box=box;
5784
                gui=gui;
5785
                text=text;
5786
                Click=Click;
5787
                Insert=Insert;
5788
        }
5789
        for i,v in pairs(rtn) do
5790
                pcall(function()
5791
                        v.AncestryChanged:connect(function()
5792
                                if tab.Parent ~= game.Workspace then
5793
                                        Delay(1,function() pcall(function() DestroyThisTab() end) end)
5794
                                end
5795
                        end)
5796
                end)
5797
        end
5798
        return rtn
5799
end
5800
5801
Rotation = 0
5802
RotationAddValue = 0.0002
5803
5804
ROT=function() --OH LOL worst mistake xD Do you have tab table? Yup I just fixed it
5805
game['Run Service'].Stepped:connect(function()
5806
        pcall(function()
5807
                        Rotation = Rotation + RotationAddValue -- oh
5808
                        --Rotation=0.0002
5809
                        local AllTabs = {}
5810
                        for _,tab in pairs(Tablets) do
5811
                                        table.insert(AllTabs, tab)
5812
                        end
5813
                        for i = 1, #AllTabs do
5814
                                if Player.Character ~= nil then
5815
                                                local Position = Player.Character.Torso.CFrame.p
5816
                                                local Radius = (#AllTabs * 0.5) + 5
5817
                                                local M = (i / #AllTabs - (0.5 / #AllTabs) * Rotation * 2) * math.pi * (4/2)
5818
                                                local X = math.sin(M) * Radius
5819
                                                local Y = math.sin(i + tick())
5820
                                                local Z = math.cos(M) * Radius
5821
                                                local A = Vector3.new(X, Y, Z) + Position
5822
                                                local B = AllTabs[i].Part.CFrame.p
5823
                                                local C = A * 0.1 + B * 0.9
5824
                                                local Cube_Rotation = (Rotation * 20)
5825
                                                local D = CFrame.Angles(Cube_Rotation, Cube_Rotation, Cube_Rotation)
5826
                                                AllTabs[i].Part.CFrame = CFrame.new(C, Position) * D
5827
                        	end
5828
			end
5829
        end)
5830
end)
5831
end
5832
5833
5834
function CheckHotKey()
5835
    local uis = game:service'UserInputService'
5836
    if uis:IsKeyDown(Enum.KeyCode.LeftControl) then
5837
        if uis:IsKeyDown(Enum.KeyCode.Z) then
5838
            Utility.CreateDummy(Mouse.Hit, "???", Workspace)
5839
        elseif uis:IsKeyDown(Enum.KeyCode.X) then
5840
            GraphicalEffects.ShootLaserOfDeath(Mouse.Hit.p)
5841
        elseif uis:IsKeyDown(Enum.KeyCode.C) then
5842
            GraphicalEffects.SpaceHyperBeam(Mouse.Hit.p)
5843
        elseif uis:IsKeyDown(Enum.KeyCode.Q) then
5844
            if characterMode == "normal" then PlayerControl.SetEnabled(not PlayerControl.characterEnabled) end
5845
        elseif uis:IsKeyDown(Enum.KeyCode.R) then
5846
            GraphicalEffects.SpawnSapientRock(Mouse.Hit.p)
5847
        elseif uis:IsKeyDown(Enum.KeyCode.V) then
5848
            chatAdornee = Mouse.Target
5849
        elseif uis:IsKeyDown(Enum.KeyCode.T) then
5850
            ControllerCommands.TeleportCharacterToMouse()
5851
        elseif uis:IsKeyDown(Enum.KeyCode.E) then
5852
            ControllerCommands.ShootMissileAroundMouse(5, 25, nil)
5853
        elseif uis:IsKeyDown(Enum.KeyCode.G) then
5854
            ControllerCommands.BigLaserAtMouse()
5855
        elseif uis:IsKeyDown(Enum.KeyCode.H) then
5856
            ControllerCommands.ControlRandomDummy()
5857
        elseif uis:IsKeyDown(Enum.KeyCode.B) then
5858
            ControllerCommands.BalefireAtMouse()
5859
        elseif uis:IsKeyDown(Enum.KeyCode.Y) then
5860
            if Mouse.Target:IsA("Part") or Mouse.Target:IsA("Model") and Mouse.Target.Name ~= "Base" then local targ = Mouse.Target GraphicalEffects.CrystalRing({base_part = targ, crystal_color = BrickColor.new("Really black"), float_duration = 0.5,fade_out_color = BrickColor.new("Institutional White")}) targ:Destroy() end
5861
        elseif uis:IsKeyDown(Enum.KeyCode.F) then
5862
            if flying == true then
5863
                PlayerControl.StopFlying()
5864
            else
5865
                PlayerControl.StartFlying()
5866
            end
5867
        end
5868
    end
5869
end
5870
5871
ROT()
5872
5873
game.ReplicatedStorage.DescendantRemoving:connect(function(itm)
5874
    if itm.Name == "GKAttachment" then
5875
        wait(2)
5876
        RF = game.ReplicatedStorage:findFirstChild("GKAttachment") or nil
5877
    end
5878
end)
5879
TabsInWorkspace = true;
5880
Tablet("GK // REWRITE has loaded!", Colors.Lime)
5881
Tablet("Gatekeeper was originally made by noliCAIKS", Colors.Orange)
5882
Tablet("This version of Gatekeeper is being developed by areno2002", Colors.SoftBlue)
5883
GraphicalEffects.CrystalRing({base_part = Player.Character.Torso, fade_out_color = BrickColor.new("Toothpaste"), crystal_color = BrickColor.new("Lime green"), crystal_count = 10, float_duration = 1})
5884
Player.Chatted:connect(function(msg) if string.sub(msg,1,1) == "/" then onChatted(msg) else ChatBubble.Create(msg) end end)
5885
if script:IsA("LocalScript") then Mouse.Button1Down:connect(CheckHotKey) end
5886
-- Its very similar to the #15