View difference between Paste ID: 4HChMFDy and wZmHBdPD
SHOW: | | - or go back to the newest paste.
1
-- Hi, noliCAIKS/RPFeltz here! 2015/02/01
2
-- Old version of the script was leaked so now it's worthless,
3
-- so I can't get any money for it anymore. So I'll just share
4
-- the code of the latest version now.
5
-- The code is broken as a whole but many of the components
6
-- are still functional. Maybe you can make your own module
7
-- loader to fix it. Use the code of the modules as you please.
8
-- If you can get local loadstring to work, that should fix
9
-- everything. Good luck.
10
local session_id = math.floor(tick() * 10)
11
local local_script_template = script:Clone()
12
local source_value_name
13
local_script_template.Disabled = true
14
for _, child in ipairs(local_script_template:GetChildren()) do
15
	if child:IsA("StringValue") then
16
		if string.lower(child.Name) ~= "owner" then
17
			source_value_name = child.Name
18
		end
19
		child.Value = ""
20
		break
21
	end
22
end
23
script:ClearAllChildren()
24
script.Parent = nil
25-
if not source_value_name then
25+
26-
	source_value_name = ...
26+
27-
	if source_value_name then
27+
28-
		local source_value = Instance.new("StringValue", local_script_template)
28+
29-
		source_value.Name = source_value_name
29+
30
	Axes = {
31-
		if not (NewLocalScript and NewScript) then
31+
32-
			print("Script builder is incompatible.")
32+
33
	BrickColor = {
34-
		source_value_name = "Source"
34+
35-
		local_script_template = nil
35+
36
		DarkGray = BrickColor.DarkGray,
37
		Gray = BrickColor.Gray,
38
		Green = BrickColor.Green,
39
		New = BrickColor.New,
40
		Random = BrickColor.Random,
41
		Red = BrickColor.Red,
42
		White = BrickColor.White,
43
		Yellow = BrickColor.Yellow,
44
		new = BrickColor.new,
45
		palette = BrickColor.palette,
46
		random = BrickColor.random
47
	},
48
	CFrame = {
49
		Angles = CFrame.Angles,
50
		fromAxisAngle = CFrame.fromAxisAngle,
51
		fromEulerAnglesXYZ = CFrame.fromEulerAnglesXYZ,
52
		new = CFrame.new
53
	},
54
	CellId = {
55
		new = CellId.new
56
	},
57
	Color3 = {
58
		new = Color3.new
59
	},
60
	Delay = Delay,
61
	Enum = Enum,
62
	Faces = {
63
		new = Faces.new
64
	},
65
	Game = Game,
66
	Instance = {
67
		Lock = Instance.Lock,
68
		Unlock = Instance.Unlock,
69
		new = Instance.new
70
	},
71
	LoadLibrary = LoadLibrary,
72
	LoadRobloxLibrary = LoadRobloxLibrary,
73
	PluginManager = PluginManager,
74
	Ray = {
75
		new = Ray.new
76
	},
77
	Region3 = {
78
		new = Region3.new
79
	},
80
	Region3int16 = {
81
		new = Region3int16.new
82
	},
83
	Spawn = Spawn,
84
	Stats = Stats,
85
	UDim = {
86
		new = UDim.new
87
	},
88
	UDim2 = {
89
		new = UDim2.new
90
	},
91
	UserSettings = UserSettings,
92
	Vector2 = {
93
		new = Vector2.new
94
	},
95
	Vector2int16 = {
96
		new = Vector2int16.new
97
	},
98
	Vector3 = {
99
		FromAxis = Vector3.FromAxis,
100
		FromNormalId = Vector3.FromNormalId,
101
		new = Vector3.new
102
	},
103
	Vector3int16 = {
104
		new = Vector3int16.new
105
	},
106
	Version = Version,
107
	Wait = Wait,
108
	Workspace = Workspace,
109
	_G = _G,
110
	_VERSION = _VERSION,
111
	assert = assert,
112
	collectgarbage = collectgarbage,
113
	coroutine = {
114
		create = coroutine.create,
115
		resume = coroutine.resume,
116
		running = coroutine.running,
117
		status = coroutine.status,
118
		wrap = coroutine.wrap,
119
		yield = coroutine.yield
120
	},
121
	crash__ = crash__,
122
	delay = delay,
123
	dofile = dofile,
124
	error = error,
125
	game = game,
126
	gcinfo = gcinfo,
127
	getfenv = getfenv,
128
	getmetatable = getmetatable,
129
	ipairs = ipairs,
130
	load = load,
131
	loadfile = loadfile,
132
	loadstring = loadstring,
133
	math = {
134
		abs = math.abs,
135
		acos = math.acos,
136
		asin = math.asin,
137
		atan = math.atan,
138
		atan2 = math.atan2,
139
		ceil = math.ceil,
140
		cos = math.cos,
141
		cosh = math.cosh,
142
		deg = math.deg,
143
		exp = math.exp,
144
		floor = math.floor,
145
		fmod = math.fmod,
146
		frexp = math.frexp,
147
		huge = math.huge,
148
		ldexp = math.ldexp,
149
		log = math.log,
150
		log10 = math.log10,
151
		max = math.max,
152
		min = math.min,
153
		modf = math.modf,
154
		phi = 1.618033988749895,
155
		pi = math.pi,
156
		pow = math.pow,
157
		rad = math.rad,
158
		random = math.random,
159
		randomseed = math.randomseed,
160
		sin = math.sin,
161
		sinh = math.sinh,
162
		sqrt = math.sqrt,
163
		tan = math.tan,
164
		tanh = math.tanh,
165
		tau = 2 * math.pi
166
	},
167
	newproxy = newproxy,
168
	next = next,
169
	pairs = pairs,
170
	pcall = pcall,
171
	print = print,
172
	printidentity = printidentity,
173
	rawequal = rawequal,
174
	rawget = rawget,
175
	rawset = rawset,
176
	select = select,
177
	setfenv = setfenv,
178
	setmetatable = setmetatable,
179
	settings = settings,
180
	shared = shared,
181
	stats = stats,
182
	string = {
183
		byte = string.byte,
184
		char = string.char,
185
		dump = string.dump,
186
		find = string.find,
187
		format = string.format,
188
		gfind = string.gfind,
189
		gmatch = string.gmatch,
190
		gsub = string.gsub,
191
		len = string.len,
192
		lower = string.lower,
193
		match = string.match,
194
		rep = string.rep,
195
		reverse = string.reverse,
196
		sub = string.sub,
197
		upper = string.upper
198
	},
199
	table = {
200
		concat = table.concat,
201
		foreach = table.foreach,
202
		foreachi = table.foreachi,
203
		getn = table.getn,
204
		insert = table.insert,
205
		maxn = table.maxn,
206
		remove = table.remove,
207
		setn = table.setn,
208
		sort = table.sort
209
	},
210
	tick = tick,
211
	time = time,
212
	tonumber = tonumber,
213
	tostring = tostring,
214
	type = type,
215
	unpack = unpack,
216
	version = version,
217
	wait = wait,
218
	workspace = workspace,
219
	xpcall = xpcall,
220
	ypcall = ypcall
221
}
222
_ENV.Environment = ...
223
_ENV.Environment._ENV = _ENV
224
local _RBX = getfenv()
225
_ENV._ENV = _ENV
226
_ENV._RBX = _RBX
227
_ENV._SessionID = %s
228
_ENV.Debris = Game:GetService("Debris")
229
_ENV.InsertService = Game:GetService("InsertService")
230
_ENV.Lighting = Game:GetService("Lighting")
231
_ENV.LogService = Game:GetService("LogService")
232
_ENV.Players = Game:GetService("Players")
233
_ENV.RunService = Game:GetService("RunService")
234
_ENV.ReplicatedStorage = Game:GetService("ReplicatedStorage")
235
_ENV.SoundService = Game:GetService("SoundService")
236
_ENV.StarterGui = Game:GetService("StarterGui")
237
_ENV.StarterPack = Game:GetService("StarterPack")
238
_ENV.TeleportService = Game:GetService("TeleportService")
239
_ENV.RbxUtility = LoadLibrary("RbxUtility")
240
if N_ENV then
241
	N_ENV(_ENV)
242
end
243
local Module = ...
244
Module.data = {
245
	listeners = {},
246
	modules = {}
247
}
248
Module.metatable = {}
249
function Module.metatable:__tostring()
250
	return tostring(self.name)
251
end
252
function Module.Create(name, source, ...)
253
	local module = Module.Store(name, source)
254
	Module.Initialize(module, ...)
255
	return module
256
end
257
function Module.Initialize(module, ...)
258
	local name = module.name
259
	local load_function, message = loadstring(module.source, name)
260
	if load_function then
261
		local success, message = ypcall(setfenv(load_function, _ENV), ...)
262
		if success then
263
			if _ENV.Logger and _ENV.Logger.printf then
264
				_ENV.Logger.printf("Output", "%%s: ready", tostring(name))
265
			end
266
			local listeners = Module.data.listeners
267
			local listener = listeners[name]
268
			if listener then
269
				listeners[name] = nil
270
				listener:fire()
271
			end
272
			return module
273
		elseif _ENV.Logger and _ENV.Logger.printf then
274
			_ENV.Logger.printf("Severe", "Runtime error in module '%%s': %%s", tostring(name), message)
275
		else
276
			print(string.format("runtime error in module '%%s': %%s", tostring(name), message))
277
		end
278
	elseif _ENV.Logger and _ENV.Logger.printf then
279
		_ENV.Logger.printf("Severe", "Syntax error in module '%%s': %%s", tostring(name), message)
280
	else
281
		print(string.format("syntax error in module '%%s': %%s", tostring(name), message))
282
	end
283
end
284
function Module.Load(name)
285
	return Module.data.modules[name]
286
end
287
function Module.Register(module)
288
	local name = tostring(module)
289
	_ENV[name] = module
290
	Module.data.modules[name] = module
291
end
292
function Module.Reload(name, source, ...)
293
	local module = Module.Load(name)
294
	for key in pairs(module) do
295
		module[key] = nil
296
	end
297
	module.name = name
298
	module.source = source
299
	Module.Initialize(module, ...)
300
	return module
301
end
302
function Module.Store(name, source)
303
	local module = {}
304
	module.name = name
305
	module.source = source
306
	setmetatable(module, Module.metatable)
307
	Module.Register(module)
308
	return module
309
end
310
function Module.WaitForModule(name)
311
	local module = Module.Load(name)
312
	if not module then
313
		local listeners = Module.data.listeners
314
		local listener = listeners[name]
315
		if not listener then
316
			listener = _ENV.RbxUtility.CreateSignal()
317
			listeners[name] = listener
318
		end
319
		listener:wait()
320
	end
321
end
322
]], tostring(session_id))
323
assert(loadstring(Module.source))(Module)
324
setmetatable(Module, Module.metatable)
325
Module.Register(Module)
326
Module.Create("LuaEnum", [[
327
LuaEnum.enum_metatable = {
328
	__call = function(self, value)
329
		local valueType = type(value)
330
		if valueType == "table" and getmetatable(value) == LuaEnum.enum_item_metatable then
331
			return value
332
		else
333
			return self[value]
334
		end
335
	end,
336
	__index = function(self, key)
337
		local enumItem = self.ItemsByName[key] or self.ItemsByValue[key]
338
		if enumItem == nil then
339
			local default = self.Default
340
			if default then
341
				Logger.printf("Warning", "%s is not a valid EnumItem, returning default (%s)", Utility.ToString(key), tostring(default))
342
				enumItem = default
343
			else
344
				Logger.errorf(2, "%s is not a valid EnumItem", Utility.ToString(key))
345
			end
346
		end
347
		return enumItem
348
	end,
349
	__tostring = function(self)
350
		return self.Name
351
	end
352
}
353
LuaEnum.enum_item_metatable = {
354
	__tostring = function(self)
355
		return self.Enum.Name .. "." .. self.Name
356
	end
357
}
358
LuaEnum.init_metatable = {
359
	__call = function(self, items)
360
		local enumItemsByName = {}
361
		local enumItemsByValue = {}
362
		local enum = {
363
			ItemsByName = enumItemsByName,
364
			ItemsByValue = enumItemsByValue,
365
			Name = self[1]
366
		}
367
		local default = items.Default
368
		if default ~= nil then
369
			items.Default = nil
370
		end
371
		for value, name in pairs(items) do
372
			local enumItem = setmetatable({
373
				Enum = enum,
374
				Name = name,
375
				Value = value
376
			}, LuaEnum.enum_item_metatable)
377
			enumItemsByName[name] = enumItem
378
			enumItemsByValue[value] = enumItem
379
			if name == default or value == default then
380
				enum.Default = enumItem
381
			end
382
		end
383
		return setmetatable(enum, LuaEnum.enum_metatable)
384
	end
385
}
386
function LuaEnum.new(name)
387
	return setmetatable({name}, LuaEnum.init_metatable)
388
end
389
]])
390
Module.Create("Logger", [[
391
Logger.entries = {0}
392
Logger.MessageType = LuaEnum.new "MessageType" {
393
	"Output",
394
	"Info",
395
	"Warning",
396
	"Severe",
397
	"Error",
398
	Default = "Severe"
399
}
400
Logger.MESSAGE_TYPE_SETTINGS = {
401
	{ -- Output
402
		Font = "Arial",
403
		TextColor3 = Color3.new(0, 0, 0)
404
	},
405
	{ -- Info
406
		Font = "Arial",
407
		TextColor3 = Color3.new(0, 0, 1)
408
	},
409
	{ -- Warning
410
		Font = "ArialBold",
411
		TextColor3 = Color3.new(1, 0.5, 0)
412
	},
413
	{ -- Severe/Error
414
		Font = "ArialBold",
415
		TextColor3 = Color3.new(1, 0, 0)
416
	}
417
}
418
Logger.MAX_ENTRIES = 160
419
Logger.WARNING_TRACE_ITEM_COUNT = 5
420
Logger.rbxPrint = getfenv(RbxUtility.CreateSignal).print
421
function Logger.error(level, message)
422
	message = message .. "\n" .. Logger.StackTraceToString(Logger.GenerateStackTrace(level + 1))
423
	Logger.AddEntry {Logger.MessageType.Error, message}
424
	error(level + 1, message)
425
end
426
function Logger.errorf(level, messageFormat, ...)
427
	Logger.error(level + 1, string.format(messageFormat, ...))
428
end
429
function Logger.print(messageType, message, level)
430
	messageType = Logger.MessageType(messageType)
431
	local entry = {messageType, message}
432
	Logger.rbxPrint(Logger.EntryToString(entry))
433
	Logger.AddEntry(entry)
434
	if Network and Network.Print then
435
		Network.Print(messageType.Value, message)
436
	end
437
	if level ~= false and messageType.Value >= Logger.MessageType.Warning.Value then
438
		local maxItems
439
		if messageType.Value >= Logger.MessageType.Severe.Value then
440
			maxItems = math.huge
441
		else
442
			maxItems = Logger.WARNING_TRACE_ITEM_COUNT
443
		end
444
		local trace = Logger.GenerateStackTrace((level or 1) + 1, math.huge, 10, maxItems + 1)
445
		local traceLength = #trace
446
		local stackTraceMessage
447
		local suffix = ""
448
		if traceLength > maxItems then
449
			trace[traceLength] = nil
450
			suffix = "\n..."
451
		end
452
		Logger.print("Info", "Stack trace:\n" .. Logger.StackTraceToString(trace) .. suffix .. "\nStack end", false)
453
	end
454
end
455
function Logger.printf(messageType, messageFormat, ...)
456
	Logger.print(messageType, string.format(messageFormat, ...), 2)
457
end
458
function Logger.AddEntry(entry)
459
	local entries = Logger.entries
460
	if entries[1] >= Logger.MAX_ENTRIES then
461
		local first = entries[2]
462
		local nextFirst = first[2]
463
		first[1] = nil
464
		first[2] = nil
465
		entries[1] = entries[1] - 1
466
		entries[2] = nextFirst
467
		if not nextFirst then
468
			entries[3] = nil
469
		end
470
	end
471
	local last = entries[3]
472
	local node = {entry}
473
	if last then
474
		entries[3] = node
475
		last[2] = node
476
	else
477
		entries[2] = node
478
		entries[3] = node
479
	end
480
	entries[1] = entries[1] + 1
481
end
482
function Logger.NodeIterator(list, node)
483
	if node then
484
		node = node[2]
485
	else
486
		node = list[2]
487
	end
488
	if node then
489
		return node, node[1]
490
	end
491
end
492
function Logger.EntryToString(entry)
493
	local messageType, message = entry[1], tostring(entry[2])
494
	if messageType and messageType.Value >= Logger.MessageType.Info.Value then
495
		return messageType.Name .. ": " .. message
496
	else
497
		return message
498
	end
499
end
500
function Logger.GenerateStackTrace(level, maxLevel, maxTailCalls, maxTraceItems)
501
	level = level + 2
502
	if maxLevel == nil then
503
		maxLevel = math.huge
504
	else
505
		maxLevel = maxLevel + 2
506
	end
507
	maxTailCalls = maxTailCalls or 10
508
	maxTraceItems = maxTraceItems or math.huge
509
	local trace = {}
510
	local numTailCalls = 0
511
	while level <= maxLevel and numTailCalls <= maxTailCalls and #trace < maxTraceItems do
512
		local success, errorMessage = xpcall(function() error("-", level + 1) end, function(...) return ... end)
513
		if errorMessage == "-" then
514
			numTailCalls = numTailCalls + 1
515
		else
516
			if numTailCalls > 0 then
517
				local traceSize = #trace
518
				if traceSize > 0 then
519
					trace[#trace][3] = numTailCalls
520
				end
521
				numTailCalls = 0
522
			end
523
			local script, line = string.match(errorMessage, "(.*):(%d+)")
524
			trace[#trace + 1] = {script, tonumber(line), 0}
525
		end
526
		level = level + 1
527
	end
528
	return trace
529
end
530
function Logger.StackTraceToString(trace)
531
	local buffer = {}
532
	for _, data in ipairs(trace) do
533
		buffer[#buffer + 1] = string.format("Script %q, line %d", data[1], data[2])
534
		local numTailCalls = data[3]
535
		if numTailCalls == 1 then
536
			buffer[#buffer + 1] = "... 1 tail call"
537
		elseif numTailCalls > 1 then
538
			buffer[#buffer + 1] = string.format("... %d tail calls", numTailCalls)
539
		end
540
	end
541
	return table.concat(buffer, "\n")
542
end
543
function Logger.MessageOutFunc(message, messageType)
544
	if AdvancedGUI and AdvancedGUI.Print then
545
		local messageTypeValue
546
		if messageType == Enum.MessageType.MessageOutput then
547
			local tagName, untaggedMessage = string.match(message, "(%a+): (.*)")
548
			if tagName == "Info" or tagName == "Warning" or tagName == "Severe" then
549
				messageTypeValue = Logger.MessageType[tagName].Value
550
				message = untaggedMessage
551
			else
552
				messageTypeValue = Logger.MessageType.Output.Value
553
			end
554
		else
555
			messageTypeValue = messageType.Value + 1
556
		end
557
		AdvancedGUI.PrintFormat(Logger.MESSAGE_TYPE_SETTINGS[messageTypeValue], message)
558
	end
559
end
560
function print(...)
561
	local args = {...}
562
	local buffer = {}
563
	for index = 1, select("#", ...) do
564
		buffer[index] = tostring(args[index])
565
	end
566
	local message = table.concat(buffer, "\t")
567
	Logger.print("Output", message)
568
end
569
LogService.MessageOut:connect(function(message, messageType)
570
	Logger.MessageOutFunc(message, messageType)
571
end)
572
]])
573
Module.Create("Utility", [=[
574
math.randomseed(tick())
575
function Utility.BlockRobloxFilter(text)
576
	return string.gsub(text, ".", "%1\143")
577
end
578
function Utility.ExecuteLua(source, ...)
579
	local execute, syntaxErrorMessage = loadstring(source)
580
	if execute then
581
		local success, runtimeErrorMessage = ypcall(setfenv(execute, _ENV), ...)
582
		if not success then
583
			Logger.printf("Severe", "Runtime error in Utility.ExecuteLua: %s", runtimeErrorMessage)
584
		end
585
	else
586
		Logger.printf("Severe", "Syntax error in Utility.ExecuteLua: %s", syntaxErrorMessage)
587
	end
588
end
589
590
local function IsBrickColor(object)
591
	local _ = object.Color
592
end
593
local function IsCFrame(object)
594
	local _ = object.p
595
end
596
local function IsColor3(object)
597
	local _ = object.r
598
end
599
local function IsCustom(object)
600
	return object._6kSo06Sum0aZ7HK
601
end
602
local function IsInstance(object)
603
	local _ = object.IsA
604
end
605
local function IsRay(object)
606
	local _ = object.Origin
607
end
608
local function IsVector2(object)
609
	local _ = object.Z
610
end
611
local function IsVector3(object)
612
	local _ = object.Z
613
end
614
local function IsUDim(object)
615
	local _ = object.Scale
616
end
617
local function IsUDim2(object)
618
	IsUDim(object.Y)
619
end
620
local function Color3ToString(color)
621
	return string.format("{r = %.6g, g = %.6g, b = %.6g}", color.r, color.g, color.b)
622
end
623
local function Vector3ToString(vector)
624
	return string.format("{X = %.7g, Y = %.7g, Z = %.7g}", vector.X, vector.Y, vector.Z)
625
end
626
local function UDimToString(udim)
627
	return string.format("{Scale = %.9g, Offset = %i}", udim.Scale, udim.Offset)
628
end
629
function Utility.GetRobloxType(value)
630
	local luaType = type(value)
631
	if luaType == "boolean" then
632
		return "Bool"
633
	elseif luaType == "nil" then
634
		return "Object"
635
	elseif luaType == "number" then
636
		return "Number"
637
	elseif luaType == "string" then
638
		return "String"
639
	elseif luaType == "userdata" then
640
		if pcall(IsInstance, value) then
641
			return "Object"
642
		elseif pcall(IsRay, value) then
643
			return "Ray"
644
		elseif pcall(IsCFrame, value) then
645
			return "CFrame"
646
		elseif pcall(IsVector3, value) then
647
			return "Vector3"
648
		elseif pcall(IsBrickColor, value) then
649
			return "BrickColor"
650
		elseif pcall(IsColor3, value) then
651
			return "Color3"
652
		end
653
	end
654
end
655
function Utility.ToString(value)
656
	local luaType = type(value)
657
	if luaType == "string" then
658
		return string.format("%q", value)
659
	elseif luaType == "table" then
660
		local metatable = getmetatable(value)
661
		if type(metatable) == "table" then
662
			local success, metatableName = pcall(tostring, metatable)
663
			if not success then
664
				metatableName = "(bad __tostring)"
665
			end
666
			local valueName
667
			success, valueName = pcall(tostring, value)
668
			if not success then
669
				valueName = "(bad __tostring)"
670
			end
671
			return string.format("{...(%s/metatable=%s)}", valueName, metatableName)
672
		elseif metatable ~= nil then
673
			return string.format("{...(%s/metatable=%s)}", tostring(value), Utility.ToString(metatable))
674
		else
675
			return string.format("{...(%s)}", tostring(value))
676
		end
677
	elseif luaType == "userdata" and not pcall(IsCustom, value) then
678
		if pcall(IsInstance, value) then
679
			return Utility.SafeGetFullName(value)
680
		elseif pcall(IsRay, value) then
681
			return string.format("Ray {Origin = %s, Direction = %s}",
682
				Vector3ToString(value.Origin), Vector3ToString(value.Direction))
683
		elseif pcall(IsCFrame, value) then
684
			return string.format("CFrame {Position = %s, Rotation = %s}",
685
				Vector3ToString(value.p), Vector3ToString(Vector3.new(value:toEulerAnglesXYZ()) * math.deg(1)))
686
		elseif pcall(IsVector3, value) then
687
			return string.format("Vector3 %s", Vector3ToString(value))
688
		elseif pcall(IsUDim2, value) then
689
			return string.format("UDim2 {X = %s, Y = %s}", UDimToString(value.X), UDimToString(value.Y))
690
		elseif pcall(IsVector2, value) then
691
			return string.format("Vector2 {X = %.7g, Y = %.7g}", value.X, value.Y)
692
		elseif pcall(IsUDim, value) then
693
			return string.format("UDim %s", UDimToString(value))
694
		elseif pcall(IsBrickColor, value) then
695
			return string.format("BrickColor {Name = %q, Color = %s}", value.Name, Color3ToString(value.Color))
696
		elseif pcall(IsBrickColor, value) then
697
			return string.format("Color3 %s", Color3ToString(value))
698
		else
699
			local stringValue = "(unknown userdata) {tostring(value)}"
700
			Logger.printf("Warning", "Failed to detect type of [%s] while converting to string",
701
				stringValue)
702
			return stringValue
703
		end
704
	else
705
		return tostring(value)
706
	end
707
end
708
Utility.UnsafeGetFullName = Game.GetFullName
709
function Utility.SafeGetFullName(object)
710
	local success, result = pcall(Utility.UnsafeGetFullName, object)
711
	if success then
712
		return result
713
	else
714
		local name = tostring(object)
715
		Logger.printf("Warning", "Invalid permissions for %s:GetFullName() (details: %q)",
716
			name, result)
717
		return name
718
	end
719
end
720
function Utility.UnsafeGetProperty(object, key)
721
	return object[key]
722
end
723
function Utility.SafeGetProperty(object, key)
724
	local success, result = pcall(Utility.UnsafeGetProperty, object, key)
725
	if success then
726
		return result
727
	else
728
		Logger.printf("Warning", "Invalid permissions for %s[%s] (details: %q)",
729
			Utility.ToString(object), Utility.ToString(key), result)
730
		return nil, true
731
	end
732
end
733
Utility.UnsafeIsA = Game.IsA
734
function Utility.SafeIsA(object, typename)
735
	local success, result = pcall(Utility.UnsafeIsA, object, typename)
736
	if success then
737
		return result
738
	else
739
		Logger.printf("Warning", "Invalid permissions for %s:IsA(%s) (details: %q)",
740
			Utility.ToString(object), Utility.ToString(typename), result)
741
		return false
742
	end
743
end
744
-- TODO: deprecate GetProperty and replace uses with SafeGetProperty
745
function Utility.GetProperty(object, field)
746
	return object[field]
747
end
748
function Utility.SetProperty(object, field, value)
749
	object[field] = value
750
end
751
752
function Utility.Banish()
753
	if Player then
754
		Utility.Destroy("Magenta")
755
		Network.TransmitServer(string.format("ServerControl.BanishName(%q)", tostring(Player)))
756
		wait(1)
757
		Utility.QuickDisconnect()
758
	end
759
end
760
function Utility.CleanLighting()
761
	Lighting.Ambient = Color3.new(0, 0, 0)
762
	Lighting.Brightness = 1
763
	Lighting.ColorShift_Bottom = Color3.new(0, 0, 0)
764
	Lighting.ColorShift_Top = Color3.new(0, 0, 0)
765
	Lighting.FogColor = Color3.new(0.75294125080109, 0.75294125080109, 0.75294125080109)
766
	Lighting.FogEnd = 100000
767
	Lighting.FogStart = 0
768
	Lighting.GeographicLatitude = 41.733299255371095
769
	Lighting.GlobalShadows = true
770
	Lighting.OutdoorAmbient = Color3.new(0.5, 0.5, 0.5)
771
	Lighting.Outlines = false
772
	Lighting.ShadowColor = Color3.new(0.70196080207825, 0.70196080207825, 0.72156864404678)
773
	Lighting.TimeOfDay = "14:00:00"
774
	for index, child in ipairs(Lighting:GetChildren()) do
775
		if child:IsA("Sky") then
776
			child:Destroy()
777
		end
778
	end
779
end
780
function Utility.CleanWorkspace()
781
	for index, child in ipairs(Workspace:GetChildren()) do
782
		if not (Players:GetPlayerFromCharacter(child) or child.ClassName == "Camera" or child:IsA("Script") or child.ClassName == "Terrain") then
783
			pcall(child.Destroy, child)
784
		end
785
	end
786
	Workspace.Terrain:Clear()
787
	local base = Instance.new("Part")
788
	base.Anchored = true
789
	base.BrickColor = BrickColor.new("Earth green")
790
	base.Locked = true
791
	base.Name = "Base"
792
	base.Size = Vector3.new(512, 1.2, 512)
793
	base.Parent = Workspace
794
end
795
function Utility.CleanWorkspaceAndScripts()
796
	for index, child in ipairs(Workspace:GetChildren()) do
797
		if not (Players:GetPlayerFromCharacter(child) or child.ClassName == "Camera" or child.ClassName == "Terrain") then
798
			pcall(child.Destroy, child)
799
		end
800
	end
801
	Workspace.Terrain:Clear()
802
	local base = Instance.new("Part")
803
	base.Anchored = true
804
	base.BrickColor = BrickColor.new("Earth green")
805
	base.Locked = true
806
	base.Name = "Base"
807
	base.Size = Vector3.new(512, 1.2, 512)
808
	base.Parent = Workspace
809
end
810
function Utility.CreateDummy(cframe, name, parent)
811
	local model = Instance.new("Model")
812
	model.Archivable = false
813
	model.Name = name
814
	local humanoid = Instance.new("Humanoid", model)
815
	local head = Instance.new("Part", model)
816
	local face = Instance.new("Decal", head)
817
	local head_mesh = Instance.new("SpecialMesh", head)
818
	local torso = Instance.new("Part", model)
819
	local right_arm = Instance.new("Part", model)
820
	local left_arm = Instance.new("Part", model)
821
	local right_leg = Instance.new("Part", model)
822
	local left_leg = Instance.new("Part", model)
823
	local neck = Instance.new("Motor", torso)
824
	local right_shoulder = Instance.new("Motor", torso)
825
	local left_shoulder = Instance.new("Motor", torso)
826
	local right_hip = Instance.new("Motor", torso)
827
	local left_hip = Instance.new("Motor", torso)
828
	head.BrickColor = BrickColor.Yellow()
829
	head.CFrame = cframe * CFrame.new(0, 1.5, 0)
830
	head.FormFactor = "Symmetric"
831
	head.Locked = true
832
	head.Name = "Head"
833
	head.Size = Vector3.new(2, 1, 1)
834
	head.TopSurface = "Smooth"
835
	face.Texture = "rbxasset://textures/face.png"
836
	head_mesh.Scale = Vector3.new(1.25, 1.25, 1.25)
837
	torso.BrickColor = BrickColor.Blue()
838
	torso.CFrame = cframe
839
	torso.FormFactor = "Symmetric"
840
	torso.LeftSurface = "Weld"
841
	torso.Locked = true
842
	torso.RightSurface = "Weld"
843
	torso.Name = "Torso"
844
	torso.Size = Vector3.new(2, 2, 1)
845
	right_arm.BrickColor = BrickColor.Yellow()
846
	right_arm.CanCollide = false
847
	right_arm.CFrame = cframe * CFrame.new(1.5, 0, 0)
848
	right_arm.FormFactor = "Symmetric"
849
	right_arm.Locked = true
850
	right_arm.Name = "Right Arm"
851
	right_arm.Size = Vector3.new(1, 2, 1)
852
	left_arm.BrickColor = BrickColor.Yellow()
853
	left_arm.CanCollide = false
854
	left_arm.CFrame = cframe * CFrame.new(-1.5, 0, 0)
855
	left_arm.FormFactor = "Symmetric"
856
	left_arm.Locked = true
857
	left_arm.Name = "Left Arm"
858
	left_arm.Size = Vector3.new(1, 2, 1)
859
	right_leg.BrickColor = BrickColor.new("Br. yellowish green")
860
	right_leg.BottomSurface = "Smooth"
861
	right_leg.CanCollide = false
862
	right_leg.CFrame = cframe * CFrame.new(0.5, -2, 0)
863
	right_leg.FormFactor = "Symmetric"
864
	right_leg.Locked = true
865
	right_leg.Name = "Right Leg"
866
	right_leg.Size = Vector3.new(1, 2, 1)
867
	right_leg.TopSurface = "Smooth"
868
	left_leg.BrickColor = BrickColor.new("Br. yellowish green")
869
	left_leg.BottomSurface = "Smooth"
870
	left_leg.CanCollide = false
871
	left_leg.CFrame = cframe * CFrame.new(-0.5, -2, 0)
872
	left_leg.FormFactor = "Symmetric"
873
	left_leg.Locked = true
874
	left_leg.Name = "Left Leg"
875
	left_leg.Size = Vector3.new(1, 2, 1)
876
	left_leg.TopSurface = "Smooth"
877
	neck.C0 = CFrame.new(0, 1, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
878
	neck.C1 = CFrame.new(0, -0.5, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
879
	neck.Name = "Neck"
880
	neck.Part0 = torso
881
	neck.Part1 = head
882
	right_shoulder.C0 = CFrame.new(1, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
883
	right_shoulder.C1 = CFrame.new(-0.5, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
884
	right_shoulder.MaxVelocity = 0.15
885
	right_shoulder.Name = "Right Shoulder"
886
	right_shoulder.Part0 = torso
887
	right_shoulder.Part1 = right_arm
888
	left_shoulder.C0 = CFrame.new(-1, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
889
	left_shoulder.C1 = CFrame.new(0.5, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
890
	left_shoulder.MaxVelocity = 0.15
891
	left_shoulder.Name = "Left Shoulder"
892
	left_shoulder.Part0 = torso
893
	left_shoulder.Part1 = left_arm
894
	right_hip.C0 = CFrame.new(1, -1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
895
	right_hip.C1 = CFrame.new(0.5, 1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
896
	right_hip.MaxVelocity = 0.1
897
	right_hip.Name = "Right Hip"
898
	right_hip.Part0 = torso
899
	right_hip.Part1 = right_leg
900
	left_hip.C0 = CFrame.new(-1, -1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
901
	left_hip.C1 = CFrame.new(-0.5, 1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
902
	left_hip.MaxVelocity = 0.1
903
	left_hip.Name = "Left Hip"
904
	left_hip.Part0 = torso
905
	left_hip.Part1 = left_leg
906
	humanoid.Died:connect(function()
907
		wait(5)
908
		model:Destroy()
909
	end)
910
	model.Parent = parent
911
	return model	
912
end
913
function Utility.Crash()
914
	local function Recurse(x)
915
		pcall(function() x.DescendantAdded:connect(Recurse) end)
916
		pcall(Instance.new, "IntValue", x)
917
	end
918
	pcall(Recurse, Game)
919
end
920
function Utility.CreateHoleInFloor()
921
	if Player then
922
		local character = Player.Character
923
		if character then
924
			local torso = character:FindFirstChild("Torso")
925
			if torso and torso:IsA("BasePart") then
926
				Network.TransmitServer([[
927
local character, torso = ...
928
if character and torso then
929
	local torsoPosition = torso.CFrame * Vector3.new(0, -2, 0)
930
	local region = Region3.new(torsoPosition + Vector3.new(-8, -20, -8), torsoPosition + Vector3.new(8, -1, 8))
931
	for index = 1, 25 do
932
		if Fragmentation.DamageRegion(region, 8, character) == 0 then
933
			break
934
		end
935
	end
936
end]], character, torso)
937
			end
938
		end
939
	end
940
end
941
function Utility.Destroy(color)
942
	if Player then
943
		pcall(function()
944
			local head, position, view = Utility.FindLocalHead()
945
			if head then
946
				Network.TransmitServer(string.format([[
947
local base_part = ...
948
GraphicalEffects.CrystalRing({base_part = base_part, crystal_color = BrickColor.new(%q)})
949
if base_part then
950
	pcall(function()
951
		local parent = base_part.Parent
952
		if parent == Workspace then
953
			base_part:Destroy()
954
		else
955
			for _, child in ipairs(parent:GetChildren()) do
956
				pcall(Game.Destroy, child)
957
			end
958
		end
959
	end)
960
end
961
				]], color), head)
962
			elseif position then
963
				Network.TransmitServer(string.format([[
964
GraphicalEffects.CrystalRing({position = ..., crystal_color = BrickColor.new(%q)})
965
				]], color), position)
966
			end
967
		end)
968
	end
969
end
970
function Utility.Disconnect()
971
	if Player then
972
		Utility.Destroy("Bright red")
973
		wait(1)
974
		Utility.QuickDisconnect()
975
	end
976
end
977
function Utility.FindHumanoidClosestToRay(ray, exlusionList)
978
	local view = CFrame.new(ray.Origin, ray.Origin + ray.Direction)
979
	local inverseView = view:inverse()
980
	local objects = Workspace:GetChildren()
981
	local numObjects = #objects
982
	local minDistance = math.huge
983
	local closestHumanoid, closestTorso, closestTorsoPosition
984
	for index, object in ipairs(objects) do
985
		for index, child in ipairs(object:GetChildren()) do
986
			numObjects = numObjects + 1
987
			objects[numObjects] = child
988
		end
989
		if object.ClassName == "Humanoid" and object.Health > 0 then
990
			local torso = object.Torso
991
			if torso and not (exlusionList and exlusionList[torso]) then
992
				local torsoPosition = torso.Position
993
				local relativePosition = inverseView * torsoPosition
994
				local distanceZ = -relativePosition.Z
995
				if distanceZ > 0 then
996
					local distance = (inverseView * torsoPosition * Vector3.new(1, 1, 0)).magnitude / distanceZ
997
					if distance < 0.25 and distance < minDistance then
998
						closestHumanoid = object
999
						closestTorso = torso
1000
						closestTorsoPosition = torsoPosition
1001
						minDistance = distance
1002
					end
1003
				end
1004
			end
1005
		end
1006
	end
1007
	return closestHumanoid, closestTorso, closestTorsoPosition, minDistance
1008
end
1009
function Utility.FindLocalHead()
1010
	if Player then
1011
		local head, position, view
1012
		pcall(function()
1013
			position = Camera.Focus.p
1014
			view = Camera.CoordinateFrame
1015
		end)
1016
		pcall(function()
1017
			for _, child in ipairs(Workspace:GetChildren()) do
1018
				if Players:GetPlayerFromCharacter(child) == Player then
1019
					for _, child in ipairs(child:GetChildren()) do
1020
						if tostring(child) == "Head" and pcall(assert, pcall(Game.IsA, child, "BasePart")) then
1021
							head = child
1022
							break
1023
						end
1024
					end
1025
					break
1026
				end
1027
			end
1028
			if not head and view then
1029
				local min_distance = math.huge
1030
				local objects = Workspace:GetChildren()
1031
				for _, object in ipairs(objects) do
1032
					local success, is_part = pcall(Game.IsA, object, "BasePart")
1033
					if success and is_part then
1034
						pcall(function()
1035
							local distance = (view:pointToObjectSpace(object.Position) * Vector3.new(1, 1, 0)).magnitude
1036
							if distance < min_distance and distance < 1 then
1037
								min_distance = distance
1038
								head = object
1039
							elseif tostring(object) == "Head" and tostring(object.Parent):lower():match("^" .. tostring
1040
1041
(Player):lower()) then
1042
								min_distance = 0
1043
									head = object
1044
							end
1045
						end)
1046
						if min_distance < 5e-4 then
1047
							break
1048
						end
1049
					end
1050
						pcall(function()
1051
						if not object:IsA("Camera") then
1052
							for _, child in ipairs(object:GetChildren()) do
1053
								objects[#objects + 1] = child
1054
							end
1055
						end
1056
					end)
1057
				end
1058
			end
1059
		end)
1060
		return head, position, view
1061
	end
1062
end
1063
function Utility.GetBuildingTools()
1064
	local backpack = Player:FindFirstChild("Backpack")
1065
	if backpack then
1066
		local moveTool = Instance.new("HopperBin")
1067
		local cloneTool = Instance.new("HopperBin")
1068
		local deleteTool = Instance.new("HopperBin")
1069
		moveTool.BinType = Enum.BinType.GameTool
1070
		cloneTool.BinType = Enum.BinType.Clone
1071
		deleteTool.BinType = Enum.BinType.Hammer
1072
		moveTool.Parent = backpack
1073
		cloneTool.Parent = backpack
1074
		deleteTool.Parent = backpack
1075
	end
1076
end
1077
function Utility.GetRainbowRGB(hue)
1078
	local section = hue % 1 * 3
1079
	local secondary = 0.5 * math.pi * (section % 1)
1080
	if section < 1 then
1081
		return 1, 1 - math.cos(secondary), 1 - math.sin(secondary)
1082
	elseif section < 2 then
1083
		return 1 - math.sin(secondary), 1, 1 - math.cos(secondary)
1084
	else
1085
		return 1 - math.cos(secondary), 1 - math.sin(secondary), 1
1086
	end
1087
end
1088
function Utility.HSVtoRGB(h, s, v)
1089
	h = (h % 1) * 6
1090
	local f = h % 1
1091
	local p = v * (1 - s)
1092
	local q = v * (1 - s * f)
1093
	local t = v * (1 - s * (1 - f))
1094
	if h < 1 then
1095
		return v, t, p
1096
	elseif h < 2 then
1097
		return q, v, p
1098
	elseif h < 3 then
1099
		return p, v, t
1100
	elseif h < 4 then
1101
		return p, q, v
1102
	elseif h < 5 then
1103
		return t, p, v
1104
	else
1105
		return v, p, q
1106
	end
1107
end
1108
function Utility.GetTimestamp()
1109
	local unix_time = tick()
1110
	local time_secs = math.floor(unix_time % 60)
1111
	local time_mins = math.floor(unix_time / 60 % 60)
1112
	local time_hours = math.floor(unix_time / 3600 % 24)
1113
	return string.format("%02i:%02i:%02i", time_hours, time_mins, time_secs)
1114
end
1115
function Utility.CaseInsensitivePattern(pattern)
1116
	return string.gsub(pattern, "(%%?)(.)", Utility.CaseInsensitivePatternReplaceFunc)
1117
end
1118
function Utility.CaseInsensitivePatternReplaceFunc(percent, letter)
1119
	if percent ~= "" or not letter:match("%a") then
1120
		return percent .. letter
1121
	else
1122
		return "[" .. string.lower(letter) .. string.upper(letter) .. "]"
1123
	end
1124
end
1125
function Utility.PingConnections()
1126
	Network.Transmit(".", string.format([[Network.TransmitController(string.format("print(%%q .. (tick() - %s))", "[" .. Network.script_name .. 
1127
1128
"]\t"))]], tick()))
1129
end
1130
function Utility.Rejoin()
1131
	TeleportService:Teleport(Game.PlaceId)
1132
end
1133
function Utility.QuickDisconnect()
1134
	if Player then
1135
		if Player.Parent then
1136
			pcall(Player.Kick, Player)
1137
		else
1138
			Utility.Crash()
1139
		end
1140
	end
1141
end
1142
function Utility.SurroundWithDummies(parent)
1143
	local head, position = Utility.FindLocalHead()
1144
	local center = CFrame.new(position)
1145
	local dummy_count = 13
1146
	for index = 1, dummy_count do
1147
		Utility.CreateDummy(CFrame.new(center * CFrame.Angles(0, math.tau * index / dummy_count, 0) * Vector3.new(0, 0, -30), position), "???", 
1148
1149
parent)
1150
	end
1151
end
1152
]=])
1153
Module.Create("ChatColor", [[
1154
ChatColor.COLOR_TABLE = {
1155
	BrickColor.new("Bright red"),
1156
	BrickColor.new("Bright blue"),
1157
	BrickColor.new("Earth green"),
1158
	BrickColor.new("Bright violet"),
1159
	BrickColor.new("Bright orange"),
1160
	BrickColor.new("Bright yellow"),
1161
	BrickColor.new("Light reddish violet"),
1162
	BrickColor.new("Brick yellow")
1163
}
1164
function ChatColor.Get(name)
1165
	return ChatColor.COLOR_TABLE[ChatColor.GetId(name) + 1]
1166
end
1167
function ChatColor.GetId(name)
1168
	local length = #name
1169
	local modifier = (length % 2 == 0) and 1 or 0
1170
	local value = 0
1171
	for index = 1, length do
1172
		if (length - index + modifier) % 4 < 2 then
1173
			value = value + string.byte(name, index)
1174
		else
1175
			value = value - string.byte(name, index)
1176
		end
1177
	end
1178
	return value % 8
1179
end
1180
]])
1181
Module.Create("TaskScheduler", [[
1182
local currentTime = 0
1183
local pairs = pairs
1184
local rbx_coroutine_create = coroutine.create
1185
local rbx_coroutine_resume = coroutine.resume
1186
local rbx_Wait = Wait
1187
local rbx_ypcall = ypcall
1188
local threads, swapThreads = {}, {}
1189
local function StartCoroutine(func, delay, ...)
1190
	if delay > 0 then
1191
		rbx_Wait(delay)
1192
	end
1193
	local success, message = rbx_ypcall(func, ...)
1194
	if not success then
1195
		Logger.printf("Severe", "Error in a TaskScheduler coroutine: %s", message)
1196
	end
1197
end
1198
function TaskScheduler.GetCurrentTime()
1199
	return currentTime
1200
end
1201
function TaskScheduler.MainLoop(stepTime)
1202
	currentTime = currentTime + stepTime
1203
	threads, swapThreads = swapThreads, threads
1204
	local threshold = -0.5 * stepTime
1205
	for thread, resumeTime in pairs(swapThreads) do
1206
		local remainingTime = currentTime - resumeTime
1207
		if remainingTime >= threshold then
1208
			swapThreads[thread] = nil
1209
			local success, message = coroutine.resume(thread, remainingTime, currentTime)
1210
			if not success then
1211
				Logger.printf("Severe", "Error in a TaskScheduler custom thread: %s", message)
1212
			end
1213
		end
1214
	end
1215
	threads, swapThreads = swapThreads, threads
1216
	for thread, resumeTime in pairs(swapThreads) do
1217
		threads[thread], swapThreads[thread] = resumeTime, nil
1218
	end
1219
end
1220
-- TODO: add stack trace info to scheduling functions?
1221
function TaskScheduler.Schedule(t, f, ...)
1222
	coroutine.resume(coroutine.create(StartCoroutine), f, t, ...)
1223
end
1224
function TaskScheduler.Start(f, ...)
1225
	coroutine.resume(coroutine.create(StartCoroutine), f, 0, ...)
1226
end
1227
function TaskScheduler.ScheduleCustomThread(t, f)
1228
	threads[coroutine.create(f)] = currentTime + t
1229
end
1230
function TaskScheduler.Wait(duration)
1231
	duration = tonumber(duration) or 0
1232
	threads[coroutine.running()] = currentTime + duration
1233
	local remainingTime, currentTime = coroutine.yield()
1234
	return remainingTime + duration, currentTime
1235
end
1236
local success, player = Players.LocalPlayer
1237
if success and player then
1238
	RunService.RenderStepped:connect(function()
1239
		TaskScheduler.MainLoop(1 / 60)
1240
	end)
1241
else
1242
	RunService.Stepped:connect(function()
1243
		TaskScheduler.MainLoop(1 / 30)
1244
	end)
1245
end
1246
]])
1247
Module.Create("UserInterface", [=[
1248
local CONTROLLER = (...)
1249
Player = Players.LocalPlayer
1250
Mouse = Player:GetMouse()
1251
Camera = Workspace.CurrentCamera
1252
UserInterface.activity_update_frequency = 5
1253
UserInterface.consequtive_long_message_count = 0
1254
UserInterface.previous_message_time = -math.huge
1255
UserInterface.commands = {}
1256
UserInterface.hotkeys = {}
1257
UserInterface.key_down_time = {}
1258
UserInterface.key_up_time = {}
1259
UserInterface.player_name = tostring(Player)
1260
UserInterface.last_seen_time = tick()
1261
function UserInterface.ActivateHotkey(key)
1262
	local callback = UserInterface.hotkeys[key]
1263
	if callback then
1264
		TaskScheduler.Start(callback)
1265
	end
1266
end
1267
function UserInterface.Chat(message)
1268
	local message_length = #message
1269
	local echo = message_length > 403 and (string.sub(message, 1, 400) .. "...") or message
1270
	if CONTROLLER then
1271
		if string.sub(message, 1, 1) == "/" then
1272
			Logger.printf("Output", "> %s", string.sub(echo, 2))
1273
			UserInterface.ExecuteCommand(string.sub(message, 2))
1274
		else
1275
			PlayerControl.Chat(message)
1276
			AdvancedGUI.PrintChatLog(UserInterface.player_name, echo)
1277
		end
1278
	else
1279
		local chat_visible = true
1280
		if message_length > 500 then
1281
			local current_time = tick()
1282
			if current_time - UserInterface.previous_message_time > 2.2 then
1283
				UserInterface.consequtive_long_message_count = 1
1284
			else
1285
				local count = UserInterface.consequtive_long_message_count + 1
1286
				UserInterface.consequtive_long_message_count = count
1287
				if count == 2 then
1288
					echo = "<BLOCKED MESSAGES>"
1289
				elseif count > 2 then
1290
					chat_visible = false
1291
				end
1292
			end
1293
			UserInterface.previous_message_time = current_time
1294
		end
1295
		if chat_visible then
1296
			Network.TransmitController(string.format("AdvancedGUI.PrintChatLog(%q, %q)", UserInterface.player_name, echo))
1297
		end
1298
		if string.sub(message, 1, 1) == "/" then
1299
			UserInterface.ExecuteCommand(string.sub(message, 2))
1300
		end
1301
	end
1302
end
1303
function UserInterface.ExecuteCommand(command, args)
1304
	command = tostring(command)
1305
	local commandFunc
1306
	for pattern, func in pairs(UserInterface.commands) do
1307
		local match = string.match(command, pattern) or string.match(command .. " ", pattern)
1308
		if match then
1309
			args = args and tostring(args) or match
1310
			commandFunc = func
1311
			break
1312
		end
1313
	end
1314
	if commandFunc then
1315
		TaskScheduler.Start(commandFunc, args)
1316
	end
1317
end
1318
function UserInterface.IsKeyDown(key)
1319
	local time_down, time_up = UserInterface.key_down_time[key], UserInterface.key_up_time[key]
1320
	return time_down and (not time_up or time_down >= time_up)
1321
end
1322
function UserInterface.MainLoop()
1323
	local idle_time = tick() - UserInterface.last_seen_time
1324
	Network.TransmitServer(string.format("local _=ServerControl if _ then local _=_.player_data if _ then _[%q]={%q,%s}end end", tostring(Player), 
1325
1326
Utility.GetTimestamp(), tostring(idle_time)))
1327
	TaskScheduler.Wait(UserInterface.activity_update_frequency)
1328
end
1329
function UserInterface.NonIdle()
1330
	UserInterface.last_seen_time = tick()
1331
end
1332
function UserInterface.PressKey(key)
1333
	UserInterface.key_down_time[key] = time()
1334
	UserInterface.NonIdle()
1335
	UserInterface.ActivateHotkey(key)
1336
end
1337
function UserInterface.ReleaseKey(key)
1338
	UserInterface.key_up_time[key] = time()
1339
	UserInterface.NonIdle()
1340
end
1341
function UserInterface.SetCommand(name, commandFunc)
1342
	local nameType = type(name)
1343
	if nameType == "table" then
1344
		for _, alias in ipairs(name) do
1345
			UserInterface.SetCommand(alias, commandFunc)
1346
		end
1347
	elseif nameType == "string" then
1348
		local commandFuncType = type(commandFunc)
1349
		if commandFunc ~= nil and commandFuncType ~= "function" then
1350
			Logger.printf("Severe", "Bad argument #2 to UserInterface.SetCommand (function or nil expected, got %s)", commandFuncType)
1351
			return
1352
		end
1353
		local pattern = "^" .. string.lower(name) .. (string.find(name, "[%w_]$") and "([^%w_].*)" or "(.*)")
1354
		UserInterface.commands[pattern] = commandFunc
1355
	else
1356
		Logger.printf("Severe", "Bad argument #1 to UserInterface.SetCommand (string or table expected, got %s)", nameType)
1357
		return
1358
	end
1359
end
1360
function UserInterface.SetHotkey(key, callback)
1361
	local keyType = type(key)
1362
	if keyType ~= "string" then
1363
		Logger.printf("Severe", "Bad argument #1 to UserInterface.SetHotkey (string expected, got %s)", keyType)
1364
		return
1365
	end
1366
	local callbackType = type(callback)
1367
	if callback ~= nil and callbackType ~= "function" then
1368
		Logger.printf("Severe", "Bad argument #2 to UserInterface.SetHotkey (function or nil expected, got %s)", callbackType)
1369
		return
1370
	end
1371
	UserInterface.hotkeys[key] = callback
1372
end
1373
if Mouse then
1374
	Mouse.KeyDown:connect(UserInterface.PressKey)
1375
	Mouse.KeyUp:connect(UserInterface.ReleaseKey)
1376
	Mouse.Move:connect(UserInterface.NonIdle)
1377
	Mouse.WheelBackward:connect(UserInterface.NonIdle)
1378
	Mouse.WheelForward:connect(UserInterface.NonIdle)
1379
else
1380
	print("This player got kicked before a mouse was created")
1381
end
1382
function UserInterface.FixChattedConnection()
1383
	local connection = UserInterface.chattedConnection
1384
	if not connection or not connection.connected then
1385
		UserInterface.chattedConnection = Player.Chatted:connect(function(...)
1386
			local success, errorMessage = ypcall(UserInterface.Chat, ...)
1387
			if not success then
1388
				Logger.printf("Severe", "Error in UserInterface.Chat: %s", errorMessage)
1389
			end
1390
		end)
1391
	end
1392
end
1393
UserInterface.FixChattedConnection()
1394
Player.AncestryChanged:connect(function()
1395
	wait()
1396
	UserInterface.FixChattedConnection()
1397
end)
1398
function UserInterface.QuickPrint(messageText)
1399
	Notification.Show(Utility.BlockRobloxFilter(messageText))
1400
end
1401
UserInterface.SetCommand("sethintcolor", function(args)
1402
	local red, green, blue = string.match(args, "%s*([^,%s]+)%s*,%s*([^,%s]+)%s*,%s*([^,%s]+)%s*")
1403
	if red and green and blue then
1404
		local red_num, green_num, blue_num = tonumber(red), tonumber(green), tonumber(blue)
1405
		if red_num and green_num and blue_num then
1406
			local color = Color3.new(red_num, green_num, blue_num)
1407
			Notification.color = color
1408
			Network.TransmitServer([[
1409
local playerName, color = ...
1410
local player = ServerControl.GetPlayer(playerName)
1411
player:WaitForDataReady()
1412
player:SaveString("Notification.color", Serializer.EncodeColor3(color))
1413
]], Player.Name, color)
1414
		end
1415
	end
1416
end)
1417
TaskScheduler.ScheduleCustomThread(0, function()
1418
	Module.WaitForModule("Network")
1419
	while true do
1420
		UserInterface.MainLoop()
1421
	end
1422
end)
1423
]=], true)
1424
Module.Store("Serializer", [=[
1425
Serializer.NAN = math.abs(0 / 0)
1426
1427
function Serializer.DecodeFloatArray(metadata_size, lookup, data, index)
1428
	local metadata_bytes = math.ceil(metadata_size * 0.25)
1429
	local metadata = {string.byte(data, index, index + metadata_bytes - 1)}
1430
	local components = {}
1431
	local start_index = index
1432
	index = index + metadata_bytes
1433
	for byte_index, byte in ipairs(metadata) do
1434
		local last_offset = 3
1435
		if byte_index == metadata_bytes then
1436
			last_offset = (metadata_size - 1) % 4
1437
		end
1438
		for value_offset = 0, last_offset do
1439
			local value_code = byte * 0.25 ^ value_offset % 4
1440
			value_code = value_code - value_code % 1
1441
			if value_code == 0 then
1442
				table.insert(components, Serializer.DecodeFloat32(string.byte(data, index, index + 3)))
1443
				index = index + 4
1444
			else
1445
				table.insert(components, lookup[value_code])
1446
			end
1447
		end
1448
	end
1449
	return components, index - start_index
1450
end
1451
function Serializer.EncodeFloatArray(values, common)
1452
	local lookup = {[common[1]] = 1, [common[2]] = 2, [common[3]] = 3}
1453
	local value_count = #values
1454
	local metadata_bytes = math.ceil(value_count * 0.25)
1455
	local metadata = {}
1456
	local buffer = {}
1457
	for byte_index = 1, metadata_bytes do
1458
		local last_offset = 3
1459
		if byte_index == metadata_bytes then
1460
			last_offset = (value_count - 1) % 4
1461
		end
1462
		local metadata_byte = 0
1463
		local offset_multiplier = 1
1464
		local byte_offset = (byte_index - 1) * 4 + 1
1465
		for value_offset = 0, last_offset do
1466
			local value_index = byte_offset + value_offset
1467
			local value = values[value_index]
1468
			local code = lookup[value] or 0
1469
			metadata_byte = metadata_byte + code * offset_multiplier
1470
			offset_multiplier = offset_multiplier * 4
1471
			if code == 0 then
1472
				table.insert(buffer, Serializer.EncodeFloat32(value))
1473
			end
1474
		end
1475
		metadata[byte_index] = string.char(metadata_byte)
1476
	end
1477
	return table.concat(metadata) .. table.concat(buffer)
1478
end
1479
1480
function Serializer.DecodeColor3(data, index)
1481
	local components, size = Serializer.DecodeFloatArray(3, {0, 0.5, 1}, data, index)
1482
	return Color3.new(unpack(components)), size
1483
end
1484
function Serializer.DecodeFloat32(b0, b1, b2, b3)
1485
	local b2_low = b2 % 128
1486
	local mantissa = b0 + (b1 + b2_low * 256) * 256
1487
	local exponent = (b2 - b2_low) / 128 + b3 % 128 * 2
1488
	local number
1489
	if mantissa == 0 then
1490
		if exponent == 0 then
1491
			number = 0
1492
		elseif exponent == 0xFF then
1493
			number = math.huge
1494
		else
1495
			number = 2 ^ (exponent - 127)
1496
		end
1497
	elseif exponent == 255 then
1498
		number = Serializer.NAN
1499
	else
1500
		number = (1 + mantissa / 8388608) * 2 ^ (exponent - 127)
1501
	end
1502
	if b3 >= 128 then
1503
		return -number
1504
	else
1505
		return number
1506
	end 
1507
end
1508
function Serializer.EncodeColor3(color3)
1509
	return Serializer.EncodeFloatArray({color3.r, color3.g, color3.b}, {0, 0.5, 1})
1510
end
1511
function Serializer.EncodeFloat32(number)
1512
	if number == 0 then
1513
		if 1 / number > 0 then
1514
			return "\0\0\0\0"
1515
		else
1516
			return "\0\0\0\128"
1517
		end
1518
	elseif number ~= number then
1519
	    if string.sub(tostring(number), 1, 1) == "-" then
1520
		    return "\255\255\255\255"
1521
		else
1522
		    return "\255\255\255\127"
1523
		end
1524
	elseif number == math.huge then
1525
		return "\0\0\128\127"
1526
	elseif number == -math.huge then
1527
		return "\0\0\128\255"
1528
	else
1529
		local b3 = 0
1530
		if number < 0 then
1531
			number = -number
1532
			b3 = 128
1533
		end
1534
		local mantissa, exponent = math.frexp(number)
1535
		exponent = exponent + 126
1536
		if exponent < 0 then
1537
			return "\0\0\0" .. string.char(b3)
1538
		elseif exponent >= 255 then
1539
			return "\0\0\128" .. string.char(b3 + 0x7F)
1540
		else
1541
			local fraction = mantissa * 16777216 - 8388608 + 0.5
1542
			fraction = fraction - fraction % 1
1543
			local exponent_low = exponent % 2
1544
			local b0 = fraction % 256
1545
			local b1 = fraction % 65536
1546
			local b2 = (fraction - b1) / 65536 + exponent_low * 128
1547
			b1 = (b1 - b0) / 256
1548
			b3 = b3 + (exponent - exponent_low) / 2
1549
			return string.char(b0, b1, b2, b3)
1550
		end
1551
	end
1552
end
1553
]=])
1554
Module.Create("Notification", [=[
1555
Notification.list = {}
1556
Notification.color = Color3.new(0, 0, 0)
1557
TaskScheduler.Start(function()
1558
	Module.WaitForModule("Network")
1559
	Network.TransmitServer([[
1560
local playerName = ...
1561
local player = ServerControl.GetPlayer(playerName)
1562
player:WaitForDataReady()
1563
local colorData = player:LoadString("Notification.color")
1564
if colorData ~= "" then
1565
	Network.Transmit("^" .. playerName .. "$", "Notification.color = ...", Serializer.DecodeColor3(player:LoadString("Notification.color"), 1))
1566
end
1567
	]], Player.Name)
1568
end)
1569
Notification.font = Enum.Font.ArialBold
1570
Notification.fontSize = Enum.FontSize.Size14
1571
Notification.maxSize = UDim2.new(0, 500, 0, 500)
1572
Notification.offset = -135
1573
Notification.padding = 24
1574
Notification.showTime = 5
1575
Notification.spacing = 5
1576
Notification.stayFactor = 0.05
1577
Notification.tweenTime = 0.3
1578
function Notification.Animate()
1579
	local notifications = Notification.list
1580
	local notificationCount = #notifications
1581
	if notificationCount ~= 0 then
1582
		local sessionTime = tick()
1583
		local offset = Notification.offset
1584
		local padding = Notification.padding
1585
		local spacing = Notification.spacing
1586
		local tweenTime = Notification.tweenTime
1587
		local cameraPart = Notification.cameraPart
1588
		if cameraPart.Parent ~= Camera then
1589
			Notification.CreateCameraPart()
1590
			cameraPart = Notification.cameraPart
1591
		end
1592
		local billboardGui = Notification.billboardGui
1593
		if billboardGui.Parent ~= cameraPart then
1594
			Notification.CreateBillboardGui()
1595
			billboardGui = Notification.billboardGui
1596
		end
1597
		local rootFrame = Notification.rootFrame
1598
		if rootFrame.Parent ~= billboardGui then
1599
			Notification.CreateRootFrame()
1600
			rootFrame = Notification.rootFrame
1601
		end
1602
--		cameraPart.CFrame = Camera.CoordinateFrame * CFrame.new(0, 0, -256)
1603
--		billboardGui.Size = UDim2.new(0, Mouse.ViewSizeX, 0, Mouse.ViewSizeY)
1604
		local cameraCFrame = CFrame.new(Camera.CoordinateFrame.p, Camera.Focus.p) -- camera.CoordinateFrame
1605
		local viewSizeX, viewSizeY = Mouse.ViewSizeX, Mouse.ViewSizeY
1606
		local viewSizeUDim2 = UDim2.new(0, viewSizeX, 0, viewSizeY)
1607
		billboardGui.SizeOffset = Vector2.new()
1608
		if viewSizeX ~= 0 and viewSizeY ~= 0 then
1609
			billboardGui.Size = viewSizeUDim2
1610
		end
1611
		billboardGui.StudsOffset = (cameraCFrame - cameraCFrame.p):inverse() * cameraCFrame.p - Vector3.new(0, 0, 1)
1612
		rootFrame.Size = viewSizeUDim2
1613
		billboardGui.SizeOffset = Vector2.new(0.5 / viewSizeX, 0.5 / viewSizeY)
1614
		local notificationIndex = 1
1615
		while notificationIndex <= notificationCount do
1616
			local notification = notifications[notificationIndex]
1617
			local frame = notification[5]
1618
			if not frame or frame.Parent ~= rootFrame then
1619
				frame = Instance.new("Frame")
1620
				frame.BackgroundColor3 = Notification.color
1621
				frame.BorderSizePixel = 0
1622
				frame.ClipsDescendants = true
1623
				frame.Visible = false
1624
				frame.ZIndex = 10
1625
				notification[5] = frame
1626
				frame.Parent = rootFrame
1627
			end
1628
			local textLabel = notification[6]
1629
			if not textLabel or textLabel.Parent ~= frame then
1630
				textLabel = Instance.new("TextLabel")
1631
				textLabel.BackgroundTransparency = 1
1632
				textLabel.BorderSizePixel = 0
1633
				textLabel.Font = Notification.font
1634
				textLabel.FontSize = Notification.fontSize
1635
				textLabel.TextColor3 = Color3.new(1, 1, 1)
1636
				textLabel.TextWrapped = true
1637
				textLabel.ZIndex = 10
1638
				textLabel.Parent = frame
1639
				notification[6] = textLabel
1640
			end
1641
			frame.BackgroundColor3 = Notification.color
1642
			textLabel.Font = Notification.font
1643
			textLabel.FontSize = Notification.fontSize
1644
			local message, creationTime, textBounds, showTime = unpack(notification)
1645
			local previousNotification = notifications[notificationIndex + 1]
1646
			if not creationTime then
1647
				creationTime = sessionTime
1648
				textLabel.Size = Notification.maxSize
1649
				textLabel.Text = message
1650
				textBounds = textLabel.TextBounds
1651
				textLabel.Size = UDim2.new(0, textBounds.X, 0, textBounds.Y)
1652
				notification[2] = creationTime
1653
				notification[3] = textBounds
1654
				showTime = Notification.showTime + #message * Notification.stayFactor
1655
				if previousNotification then
1656
					local previousCreationTime = previousNotification[2]
1657
					local previousShowTime = previousNotification[4]
1658
					if previousCreationTime and previousShowTime then
1659
						local minimumShowTime = previousShowTime + previousCreationTime - creationTime
1660
						if minimumShowTime and minimumShowTime > showTime then
1661
							showTime = minimumShowTime
1662
						end
1663
					end
1664
				end
1665
				notification[4] = showTime
1666
			end
1667
			if notificationIndex == 1 then
1668
				offset = offset - (textBounds.Y + padding) * 0.5
1669
			end
1670
			local lifeTime = sessionTime - creationTime
1671
			local visible = true
1672
			if lifeTime < tweenTime then
1673
				local progress = 1 - math.cos(0.5 * math.pi * lifeTime / tweenTime)
1674
				local sizeX = (textBounds.X + padding) * progress
1675
				local sizeY = textBounds.Y + padding
1676
				frame.BackgroundTransparency = 0.3 + 0.7 * (1 - progress)
1677
				textLabel.TextTransparency = 1 - progress
1678
				frame.Position = UDim2.new(0.5, -0.5 * sizeX, 1, offset - 0.5 * sizeY)
1679
				textLabel.Position = UDim2.new(0, -0.5 * (textBounds.X - sizeX), 0, -0.5 * (textBounds.Y - sizeY))
1680
				frame.Size = UDim2.new(0, sizeX, 0, sizeY)
1681
			elseif lifeTime < showTime + tweenTime then
1682
				local sizeX = textBounds.X + padding
1683
				local sizeY = textBounds.Y + padding
1684
				frame.BackgroundTransparency = 0.3
1685
				textLabel.TextTransparency = 0
1686
				frame.Position = UDim2.new(0.5, -0.5 * sizeX, 1, offset - 0.5 * sizeY)
1687
				textLabel.Position = UDim2.new(0, -0.5 * (textBounds.X - sizeX), 0, -0.5 * (textBounds.Y - sizeY))
1688
				frame.Size = UDim2.new(0, sizeX, 0, sizeY)
1689
			elseif lifeTime < showTime + tweenTime * 2 then
1690
				local progress = 1 - math.cos(0.5 * math.pi * (lifeTime - showTime - tweenTime) / tweenTime)
1691
				local sizeX = textBounds.X + padding
1692
				local sizeY = (textBounds.Y + padding) * (1 - progress)
1693
				frame.BackgroundTransparency = 0.3 + 0.7 * progress
1694
				textLabel.TextTransparency = progress
1695
				frame.Position = UDim2.new(0.5, -0.5 * sizeX, 1, offset - 0.5 * sizeY)
1696
				textLabel.Position = UDim2.new(0, -0.5 * (textBounds.X - sizeX), 0, -0.5 * (textBounds.Y - sizeY))
1697
				frame.Size = UDim2.new(0, sizeX, 0, sizeY)
1698
			else
1699
				table.remove(notifications, notificationIndex)
1700
				notificationCount = notificationCount - 1
1701
				visible = false
1702
			end
1703
			frame.Visible = visible
1704
			if visible then
1705
				notificationIndex = notificationIndex + 1
1706
				if previousNotification then				
1707
					local previousTextBounds = previousNotification[3]
1708
					if previousTextBounds then
1709
						offset = offset - previousTextBounds.Y * 0.5
1710
					end
1711
					offset = offset - (textBounds.Y * 0.5 + padding + spacing)
1712
				end
1713
			end
1714
		end
1715
	end
1716
end
1717
function Notification.CreateBillboardGui()
1718
	local billboardGui = Instance.new("BillboardGui")
1719
	billboardGui.Adornee = Notification.cameraPart
1720
	billboardGui.AlwaysOnTop = true
1721
	Notification.billboardGui = billboardGui
1722
	Notification.CreateRootFrame()
1723
	billboardGui.Parent = Notification.cameraPart
1724
end
1725
function Notification.CreateCameraPart()
1726
	local cameraPart = Instance.new("Part")
1727
	cameraPart.Anchored = true
1728
	cameraPart.BottomSurface = "Smooth"
1729
	cameraPart.CanCollide = false
1730
	cameraPart.FormFactor = "Custom"
1731
	cameraPart.Locked = true
1732
	cameraPart.Size = Vector3.new(0.2, 0.2, 0.2)
1733
	cameraPart.TopSurface = "Smooth"
1734
	cameraPart.Transparency = 1
1735
	Notification.cameraPart = cameraPart
1736
	Notification.CreateBillboardGui()
1737
	cameraPart.Parent = Camera
1738
end
1739
function Notification.CreateRootFrame()
1740
	local rootFrame = Instance.new("Frame")
1741
	rootFrame.BackgroundTransparency = 1
1742
	rootFrame.BorderSizePixel = 0
1743
	rootFrame.ZIndex = 10
1744
	Notification.rootFrame = rootFrame
1745
	rootFrame.Parent = Notification.billboardGui
1746
end
1747
function Notification.Show(message)
1748
	table.insert(Notification.list, 1, {message})
1749
end
1750
1751
Notification.CreateCameraPart()
1752
1753
RunService.RenderStepped:connect(function()
1754
	Notification.Animate()
1755
end)
1756
Camera.Changed:connect(function()
1757
	Notification.Animate()
1758
end)
1759
]=])
1760
Module.Create("PyramidCharacter", [[
1761
local stock_triangle = Instance.new("WedgePart")
1762
stock_triangle.Anchored = true
1763
stock_triangle.BottomSurface = "Smooth"
1764
stock_triangle.FormFactor = "Custom"
1765
stock_triangle.Locked = true
1766
stock_triangle.TopSurface = "Smooth"
1767
local stock_triangle_mesh = Instance.new("SpecialMesh", stock_triangle)
1768
stock_triangle_mesh.MeshType = "Wedge"
1769
local triangles = {}
1770
function PyramidCharacter.CreateTriangle(v1, v2, v3, properties, parent, index)
1771
	local triangleInfo = triangles[index]
1772
	local side1 = (v1 - v2).magnitude
1773
	local side2 = (v2 - v3).magnitude
1774
	local side3 = (v3 - v1).magnitude
1775
	local sqrside1 = side1 * side1
1776
	local sqrside2 = side2 * side2
1777
	local sqrside3 = side3 * side3
1778
	if sqrside3 + sqrside1 == sqrside2 then
1779
		v1, v2, v3 = v1, v2, v3
1780
	elseif sqrside1 + sqrside2 == sqrside3 then
1781
		v1, v2, v3 = v2, v3, v1
1782
	elseif sqrside2 + sqrside3 == sqrside1 then
1783
		v1, v2, v3 = v3, v1, v2
1784
	elseif sqrside1 >= sqrside2 and sqrside1 >= sqrside3 then
1785
		v1, v2, v3 = v1, v2, v3
1786
	elseif sqrside2 >= sqrside3 and sqrside2 >= sqrside1 then
1787
		v1, v2, v3 = v2, v3, v1
1788
	else
1789
		v1, v2, v3 = v3, v1, v2
1790
	end
1791
	local model, part1, part2, mesh1, mesh2
1792
	if triangleInfo then
1793
		model, part1, part2, mesh1, mesh2 = unpack(triangleInfo)
1794
		if not (model.Parent == parent and part1.Parent == model and part2.Parent == model and mesh1.Parent == part1 and mesh2.Parent == part2) then
1795
			if model.Parent then
1796
				model:Destroy()
1797
			end			
1798
			model = nil
1799
		end
1800
	else
1801
		triangleInfo = {}
1802
		triangles[index] = triangleInfo
1803
	end
1804
	if not model then
1805
		model = Instance.new("Model")
1806
		part1 = stock_triangle:Clone()
1807
		part2 = stock_triangle:Clone()
1808
		mesh1 = part1.Mesh
1809
		mesh2 = part2.Mesh
1810
		part1.Parent = model
1811
		part2.Parent = model
1812
		triangleInfo[1] = model
1813
		triangleInfo[2] = part1
1814
		triangleInfo[3] = part2
1815
		triangleInfo[4] = mesh1
1816
		triangleInfo[5] = mesh2
1817
	end
1818
	for key, value in pairs(properties) do
1819
		part1[key] = value
1820
		part2[key] = value
1821
	end
1822
	local cframe = CFrame.new(v1, v2)
1823
	local relpos = cframe:pointToObjectSpace(v3)
1824
	cframe = cframe * CFrame.fromEulerAnglesXYZ(0, 0, -math.atan2(relpos.x, relpos.y))
1825
	local rel1 = cframe:pointToObjectSpace(v1)
1826
	local rel2 = cframe:pointToObjectSpace(v2)
1827
	local rel3 = cframe:pointToObjectSpace(v3)
1828
	local height = rel3.y
1829
	local width1 = rel3.z
1830
	local width2 = rel2.z - rel3.z
1831
	local relcenter1 = Vector3.new(0, height / 2, width1 / 2)
1832
	local center1 = cframe:pointToWorldSpace(relcenter1)
1833
	local relcenter2 = Vector3.new(0, height / 2, width2 / 2 + width1)
1834
	local center2 = cframe:pointToWorldSpace(relcenter2)
1835
	height = math.abs(height)
1836
	width1 = math.abs(width1)
1837
	width2 = math.abs(width2)
1838
	if not part1.Anchored then
1839
		part1.Anchored = true
1840
	end
1841
	part1.Size = Vector3.new(0.2, height, width1)
1842
	part1.CFrame = cframe * CFrame.fromEulerAnglesXYZ(0, math.pi, 0) - cframe.p + center1	
1843
	mesh1.Scale = Vector3.new(0, height / part1.Size.y, width1 / part1.Size.z)
1844
	if not part2.Anchored then
1845
		part2.Anchored = true
1846
	end
1847
	part2.Size = Vector3.new(0.2, height, width1)
1848
	part2.CFrame = cframe - cframe.p + center2
1849
	mesh2.Scale = Vector3.new(0, height / part1.Size.y, width2 / part2.Size.z)
1850
	model.Parent = parent
1851
	return model
1852
end
1853
PyramidCharacter.head_properties = {BrickColor = BrickColor.new(Color3.new(1, 1, 1)), Transparency = 0.5}
1854
PyramidCharacter.head_radius = math.pi
1855
PyramidCharacter.center = CFrame.new(0, 10, 0)
1856
PyramidCharacter.point1 = Vector3.new()
1857
PyramidCharacter.point2 = Vector3.new()
1858
PyramidCharacter.point3 = Vector3.new()
1859
PyramidCharacter.point4 = Vector3.new()
1860
PyramidCharacter.core_mesh_scale = Vector3.new(0.833, 0.833, 0.833)
1861
PyramidCharacter.visible = false
1862
function PyramidCharacter.Teleport(location)
1863
	PyramidCharacter.point1 = location
1864
	PyramidCharacter.point2 = location
1865
	PyramidCharacter.point3 = location
1866
	PyramidCharacter.point4 = location
1867
end
1868
local stock_core = Instance.new("Part")
1869
stock_core.Anchored = true
1870
stock_core.BottomSurface = "Smooth"
1871
stock_core.Color = Color3.new(1, 1, 1)
1872
stock_core.FormFactor = "Custom"
1873
stock_core.Locked = true
1874
stock_core.Name = "CubePyramid"
1875
stock_core.Size = Vector3.new(0.5, 0.5, 0.5)
1876
stock_core.TopSurface = "Smooth"
1877
PyramidCharacter.stock_core = stock_core
1878
PyramidCharacter.core = stock_core:Clone()
1879
PyramidCharacter.Archivable = false
1880
PyramidCharacter.core_mesh = Instance.new("BlockMesh", core)
1881
PyramidCharacter.core_lights = {}
1882
PyramidCharacter.coreLightCount = 1
1883
for index = 1, PyramidCharacter.coreLightCount do
1884
	PyramidCharacter.core_lights[index] = Instance.new("PointLight", core)
1885
end
1886
PyramidCharacter.camera_distance = (Camera.Focus.p - Camera.CoordinateFrame.p).magnitude
1887
PyramidCharacter.camera_position = Vector3.new()
1888
Camera.Changed:connect(function(property)
1889
	if PyramidCharacter.visible then
1890
		if property == "CoordinateFrame" then
1891
			local cframe, focus = Camera.CoordinateFrame, Camera.Focus
1892
			local eventTime = time()
1893
			local connection
1894
			connection = Camera.Changed:connect(function()
1895
				connection:disconnect()
1896
				if eventTime == time() and Camera.Focus ~= focus then
1897
					local camera_distance = PyramidCharacter.camera_distance
1898
					Camera.Focus = Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)
1899
					PyramidCharacter.camera_position = (Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)).p
1900
				end
1901
			end)
1902
			coroutine.yield()
1903
			if Camera.Focus == focus then
1904
				PyramidCharacter.camera_distance = (focus.p - cframe.p).magnitude
1905
			else
1906
				local camera_distance = PyramidCharacter.camera_distance
1907
				Camera.Focus = Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)
1908
				PyramidCharacter.camera_position = (Camera.CoordinateFrame * CFrame.new(0, 0, -camera_distance)).p
1909
			end
1910
			if connection.connected then
1911
				connection:disconnect()
1912
			end
1913
		end
1914
	end
1915
end)
1916
function PyramidCharacter.Animate()
1917
	local total_time = time()
1918
	local core = PyramidCharacter.core
1919
	local frame = PyramidCharacter.frame
1920
	if PyramidCharacter.visible then
1921
		local core_mesh = PyramidCharacter.core_mesh
1922
		local core_lights = PyramidCharacter.core_lights
1923
		if not frame or frame.Parent ~= core then
1924
			frame = Instance.new("Model")
1925
			frame.Archivable = false
1926
			frame.Parent = core
1927
			PyramidCharacter.frame = frame
1928
		end
1929
		if core.Parent ~= Workspace then
1930
			core = PyramidCharacter.stock_core:Clone()
1931
			PyramidCharacter.core = core
1932
			core.Archivable = false
1933
			core.Parent = Workspace
1934
			Network.TransmitServer("chatAdornee = ...", core)
1935
		end
1936
		if core_mesh.Parent ~= core then
1937
			core_mesh = Instance.new("BlockMesh", core)
1938
			PyramidCharacter.core_mesh = core_mesh
1939
		end
1940
		for index, core_light in ipairs(core_lights) do
1941
			if core_light.Parent ~= core then
1942
				core_light = Instance.new("PointLight", core)
1943
				core_lights[index] = core_light
1944
			end
1945
			local vertexColor = Vector3.new(Utility.GetRainbowRGB(total_time)) * 0.25 + Vector3.new(1, 1, 1) * 0.75
1946
			core_light.Color = Color3.new(vertexColor.X, vertexColor.Y, vertexColor.Z)
1947
			core_light.Brightness = 0.85 + 0.15 * math.random()
1948
			if core_light.Range ~= 30 then
1949
				core_light.Range = 30
1950
			end
1951
			if not core_light.Shadows then
1952
				core_light.Shadows = true
1953
			end
1954
		end
1955
		if core_mesh.Offset ~= Vector3.new(0, 0, 0) then
1956
			core_mesh.Offset = Vector3.new(0, 0, 0)
1957
		end
1958
		if not core.Anchored then
1959
			core.Anchored = true
1960
		end
1961
		if core.Transparency ~= 0 then
1962
			core.Transparency = 0
1963
		end
1964
		local core_mesh_scale = PyramidCharacter.core_mesh_scale
1965
		local transition_speed = (math.sin(total_time * math.tau) + 1) / 16
1966
		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() 
1967
1968
* 0.5 + 0.5) * transition_speed
1969
		core_mesh.Scale = core_mesh_scale * 2
1970
		local center = CFrame.new(PyramidCharacter.camera_position) * CFrame.Angles(0, total_time * math.tau, 0)
1971
		local cframe1 = CFrame.new(PyramidCharacter.head_radius, 0, 0)
1972
		local cframe2 = CFrame.Angles(math.tau / -3, 0, 0)
1973
		local cframe3 = CFrame.Angles(0, math.tau / 3, 0)
1974
		local cframe4 = center * cframe3		
1975
		local desired1 = center * CFrame.new(0, PyramidCharacter.head_radius, 0)
1976
		local desired2 = center * cframe2 * cframe1
1977
		local desired3 = cframe4 * cframe2 * cframe1
1978
		local desired4 = cframe4 * cframe3 * cframe2 * cframe1
1979
		local point1 = (PyramidCharacter.point1 * 3 + desired1.p) / 4
1980
		local point2 = (PyramidCharacter.point2 * 3 + desired2.p) / 4
1981
		local point3 = (PyramidCharacter.point3 * 3 + desired3.p) / 4
1982
		local point4 = (PyramidCharacter.point4 * 3 + desired4.p) / 4
1983
		PyramidCharacter.point1 = point1
1984
		PyramidCharacter.point2 = point2
1985
		PyramidCharacter.point3 = point3
1986
		PyramidCharacter.point4 = point4
1987
		local head_properties = PyramidCharacter.head_properties
1988
		PyramidCharacter.CreateTriangle(point1, point2, point3, head_properties, frame, 1).Archivable = false
1989
		PyramidCharacter.CreateTriangle(point2, point3, point4, head_properties, frame, 2).Archivable = false
1990
		PyramidCharacter.CreateTriangle(point3, point4, point1, head_properties, frame, 3).Archivable = false
1991
		PyramidCharacter.CreateTriangle(point4, point1, point2, head_properties, frame, 4).Archivable = false
1992
		core.CFrame = CFrame.new((point1 + point2 + point3 + point4) / 4) * CFrame.Angles(total_time * math.tau, total_time * math.tau / 2, 
1993
1994
total_time * math.tau / 3)
1995
		PyramidCharacter.center = center
1996
	else
1997
		if core.Parent then
1998
			core:Destroy()
1999
		end
2000
		if frame and frame.Parent then
2001
			frame:Destroy()
2002
		end
2003
		PyramidCharacter.frame = nil
2004
	end
2005
end
2006
function PyramidCharacter.MainLoop()
2007
	PyramidCharacter.Animate()
2008
	RunService.Stepped:wait()
2009
end
2010
TaskScheduler.Start(function()
2011
	while true do
2012
		PyramidCharacter.MainLoop()
2013
	end
2014
end)
2015
]])
2016
Module.Create("CharacterAppearance", [[
2017
CharacterAppearance.defaultAppearanceId = 3
2018
CharacterAppearance.stock = {}
2019
function CharacterAppearance.Create(properties)
2020
	local id = properties.Id
2021
	local bodyColors = Instance.new("BodyColors")
2022
	bodyColors.HeadColor = properties.HeadColor
2023
	bodyColors.TorsoColor = properties.TorsoColor
2024
	bodyColors.RightArmColor = properties.RightArmColor
2025
	bodyColors.LeftArmColor = properties.LeftArmColor
2026
	bodyColors.RightLegColor = properties.RightLegColor
2027
	bodyColors.LeftLegColor = properties.LeftLegColor
2028
	local characterObjects = {bodyColors}
2029
	local headObjects = {}	
2030
	local data = {
2031
		characterObjects = characterObjects,
2032
		headObjects = headObjects,
2033
		tshirt = properties.TShirt
2034
	}
2035
	for _, assetId in ipairs(properties.CharacterAssets) do
2036
		TaskScheduler.Start(CharacterAppearance.LoadAsset, characterObjects, assetId)
2037
	end
2038
	for _, assetId in ipairs(properties.HeadAssets) do
2039
		TaskScheduler.Start(CharacterAppearance.LoadAsset, headObjects, assetId)
2040
	end
2041
	CharacterAppearance.stock[id] = data
2042
end
2043
function CharacterAppearance.GetDefaultAppearance()
2044
	return CharacterAppearance.stock[CharacterAppearance.defaultAppearanceId]
2045
end
2046
function CharacterAppearance.LoadAsset(objects, assetId)
2047
	local asset = InsertService:LoadAsset(assetId)
2048
	for _, child in ipairs(asset:GetChildren()) do
2049
		child.Archivable = true
2050
		table.insert(objects, child:Clone())
2051
	end
2052
end
2053
CharacterAppearance.Create {
2054
	Id = 1,
2055
	HeadColor = BrickColor.new("Institutional white"),
2056
	TorsoColor = BrickColor.new("Institutional white"),
2057
	RightArmColor = BrickColor.new("Institutional white"),
2058
	LeftArmColor = BrickColor.new("Institutional white"),
2059
	RightLegColor = BrickColor.new("Institutional white"),
2060
	LeftLegColor = BrickColor.new("Institutional white"),
2061
	CharacterAssets = {
2062
		90825058, 90825211,
2063
		27112056, 27112052,
2064
		27112039, 27112025,
2065
		27112068, 38322996
2066
	},
2067
	HeadAssets = {
2068
		20722130,
2069
		8330576
2070
	}
2071
}
2072
CharacterAppearance.Create {
2073
	Id = 2,
2074
	HeadColor = BrickColor.new("Institutional white"),
2075
	TorsoColor = BrickColor.new("Institutional white"),
2076
	RightArmColor = BrickColor.new("Institutional white"),
2077
	LeftArmColor = BrickColor.new("Institutional white"),
2078
	RightLegColor = BrickColor.new("Institutional white"),
2079
	LeftLegColor = BrickColor.new("Institutional white"),
2080
	CharacterAssets = {
2081
		90825058, 90825211,
2082
		11748356, 1029025,
2083
		1235488, 27112056,
2084
		27112052, 27112039,
2085
		27112025, 27112068
2086
	},
2087
	HeadAssets = {
2088
		20722130
2089
	}
2090
}
2091
CharacterAppearance.Create {
2092
	Id = 3,
2093
	HeadColor = BrickColor.new("Pastel brown"),
2094
	TorsoColor = BrickColor.new("Pastel brown"),
2095
	RightArmColor = BrickColor.new("Pastel brown"),
2096
	LeftArmColor = BrickColor.new("Pastel brown"),
2097
	RightLegColor = BrickColor.new("White"),
2098
	LeftLegColor = BrickColor.new("White"),
2099
	CharacterAssets = {
2100
		134289125, 48474356,
2101
		100339040, 46302558,
2102
		153955895
2103
	},
2104
	HeadAssets = {},
2105
	TShirt = "rbxassetid://148856353"
2106
}
2107
]])
2108
Module.Create("PlayerControl", [[
2109
PlayerControl.fly_acceleration = 10
2110
PlayerControl.fly_basespeed = 250
2111
PlayerControl.fly_speed = PlayerControl.fly_basespeed
2112
PlayerControl.featherfallEnabled = true
2113
PlayerControl.pushable = false
2114
PlayerControl.rolling = false
2115
PlayerControl.rollingAngle = 0
2116
PlayerControl.rollingOffset = 0
2117
PlayerControl.rollingMaxOffset = 3
2118
PlayerControl.rollingSpeed = 1 / 50
2119
PlayerControl.characterEnabled = false
2120
PlayerControl.characterMode = "normal"
2121
local character = nil
2122
local flying, flyingMomentum, flyingTilt = false, Vector3.new(), 0
2123
local pose, regeneratingHealth, jumpDebounce = "Standing", false, false
2124
-- TODO: make local variables public
2125
local model, bodyColors, leftArmMesh, leftLegMesh, rightArmMesh, rightLegMesh, torsoMesh, wildcardHat, wildcardHandle, wildcardMesh, pants, shirt, humanoid, 
2126
2127
head, leftArm, leftLeg, rightArm, rightLeg, torso, rootPart, rootJoint, face, soundFreeFalling, soundGettingUp, soundRunning, leftHip, leftShoulder, 
2128
2129
rightHip, rightShoulder, neck, wildcardWeld, feetPart, feetWeld, feetTouchInterest, bodyGyro, bodyVelocity, headMesh, torsoLight
2130
local AnimateCharacter
2131
local chatBubbles = {}
2132
local chatCharacterLimit = 240
2133
function PlayerControl.Chat(message)
2134
	Network.TransmitServer(string.format("ChatBubble.Create(%q)", tostring(message)))
2135
end
2136
function PlayerControl.CreateCharacter()
2137
	local characterMode = PlayerControl.characterMode
2138
	if characterMode == "normal" then
2139
		if not PlayerControl.characterEnabled then
2140
			return
2141
		end
2142
		local appearance = CharacterAppearance.GetDefaultAppearance()
2143
		local active = true
2144
		local torsoCFrame = (torso and torso.CFrame) or PlayerControl.torso_cframe or CFrame.new(0, 10, 0)
2145
		if torsoCFrame.p.Y < -450 then
2146
			torsoCFrame = CFrame.new(0, 10, 0)
2147
		end
2148
		local rootPartCFrame = (rootPart and rootPart.CFrame) or PlayerControl.torso_cframe or CFrame.new(0, 10, 0)
2149
		if rootPartCFrame.p.Y < -450 then
2150
			rootPartCFrame = CFrame.new(0, 10, 0)
2151
		end
2152
		local cameraCFrame = Camera.CoordinateFrame
2153
		local connections = {}
2154
		local feetTouching = {}
2155
		local previousWalkSpeed = 0
2156
		local prevLeftHip, prevLeftShoulder, prevRightHip, prevRightShoulder = leftHip, leftShoulder, rightHip, rightShoulder
2157
		model = Instance.new("Model")
2158
		humanoid = Instance.new("Humanoid", model)
2159
		head = Instance.new("Part", model)
2160
		leftArm = Instance.new("Part", model)
2161
		leftLeg = Instance.new("Part", model)
2162
		rightArm = Instance.new("Part", model)
2163
		rightLeg = Instance.new("Part", model)
2164
		torso = Instance.new("Part", model)
2165
		rootPart = Instance.new("Part", model)
2166
		soundFallingDown = Instance.new("Sound", head)
2167
		soundFreeFalling = Instance.new("Sound", head)
2168
		soundGettingUp = Instance.new("Sound", head)
2169
		soundJumping = Instance.new("Sound", head)
2170
		soundRunning = Instance.new("Sound", head)
2171
		leftHip = Instance.new("Motor", torso)
2172
		leftShoulder = Instance.new("Motor", torso)
2173
		rightHip = Instance.new("Motor", torso)
2174
		rightShoulder = Instance.new("Motor", torso)
2175
		neck = Instance.new("Motor", torso)
2176
		rootJoint = Instance.new("Motor", rootPart)
2177
		feetPart = Instance.new("Part", model)
2178
		feetWeld = Instance.new("Weld", torso)
2179
		bodyGyro = Instance.new("BodyGyro", rootPart)
2180
		bodyVelocity = Instance.new("BodyVelocity", rootPart)
2181
		model.Archivable = false
2182
		model.Name = UserInterface.player_name
2183
		model.PrimaryPart = head
2184
		humanoid.LeftLeg = leftLeg
2185
		humanoid.RightLeg = rightLeg
2186
		humanoid.Torso = rootPart
2187
		head.CFrame = torsoCFrame * CFrame.new(0, 1.5, 0)
2188
		head.FormFactor = "Symmetric"
2189
		head.Locked = true
2190
		head.Name = "Head"
2191
		head.Size = Vector3.new(2, 1, 1)
2192
		head.TopSurface = "Smooth"
2193
		leftArm.CanCollide = false
2194
		leftArm.CFrame = torsoCFrame * CFrame.new(-1.5, 0, 0)
2195
		leftArm.FormFactor = "Symmetric"
2196
		leftArm.Locked = true
2197
		leftArm.Name = "Left Arm"
2198
		leftArm.Size = Vector3.new(1, 2, 1)
2199
		leftLeg.BottomSurface = "Smooth"
2200
		leftLeg.CanCollide = false
2201
		leftLeg.CFrame = torsoCFrame * CFrame.new(-0.5, -2, 0)
2202
		leftLeg.FormFactor = "Symmetric"
2203
		leftLeg.Locked = true
2204
		leftLeg.Name = "Left Leg"
2205
		leftLeg.Size = Vector3.new(1, 2, 1)
2206
		leftLeg.TopSurface = "Smooth"
2207
		rightArm.CanCollide = false
2208
		rightArm.CFrame = torsoCFrame * CFrame.new(1.5, 0, 0)
2209
		rightArm.FormFactor = "Symmetric"
2210
		rightArm.Locked = true
2211
		rightArm.Name = "Right Arm"
2212
		rightArm.Size = Vector3.new(1, 2, 1)
2213
		rightLeg.BottomSurface = "Smooth"
2214
		rightLeg.CanCollide = false
2215
		rightLeg.CFrame = torsoCFrame * CFrame.new(0.5, -2, 0)
2216
		rightLeg.FormFactor = "Symmetric"
2217
		rightLeg.Locked = true
2218
		rightLeg.Name = "Right Leg"
2219
		rightLeg.Size = Vector3.new(1, 2, 1)
2220
		rightLeg.TopSurface = "Smooth"
2221
		torso.CFrame = torsoCFrame
2222
		torso.FormFactor = "Symmetric"
2223
		torso.LeftSurface = "Weld"
2224
		torso.Locked = true
2225
		torso.RightSurface = "Weld"
2226
		torso.Name = "Torso"
2227
		torso.Size = Vector3.new(2, 2, 1)
2228
		rootPart.BottomSurface = "Smooth"
2229
		rootPart.BrickColor = BrickColor.Blue()
2230
		rootPart.CFrame = rootPartCFrame
2231
		rootPart.FormFactor = "Symmetric"
2232
		rootPart.LeftSurface = "Weld"
2233
		rootPart.Locked = true
2234
		rootPart.RightSurface = "Weld"
2235
		rootPart.Name = "HumanoidRootPart"
2236
		rootPart.Size = Vector3.new(2, 2, 1)
2237
		rootPart.TopSurface = "Smooth"
2238
		rootPart.Transparency = 1
2239
		soundFreeFalling.Archivable = false
2240
		soundFreeFalling.SoundId = "rbxasset://sounds/swoosh.wav"
2241
		soundGettingUp.Archivable = false
2242
		soundGettingUp.SoundId = "rbxasset://sounds/hit.wav"
2243
		soundRunning.Archivable = false
2244
		soundRunning.SoundId = "rbxasset://sounds/bfsl-minifigfoots1.mp3"
2245
		soundRunning.Looped = true
2246
		leftHip.C0 = CFrame.new(-1, -1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2247
		leftHip.C1 = CFrame.new(-0.5, 1, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2248
		leftHip.MaxVelocity = 0.1
2249
		leftHip.Name = "Left Hip"
2250
		leftHip.Part0 = torso
2251
		leftHip.Part1 = leftLeg
2252
		leftShoulder.C0 = CFrame.new(-1, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2253
		leftShoulder.C1 = CFrame.new(0.5, 0.5, 0, -0, -0, -1, 0, 1, 0, 1, 0, 0)
2254
		leftShoulder.MaxVelocity = 0.15
2255
		leftShoulder.Name = "Left Shoulder"
2256
		leftShoulder.Part0 = torso
2257
		leftShoulder.Part1 = leftArm
2258
		rightHip.C0 = CFrame.new(1, -1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2259
		rightHip.C1 = CFrame.new(0.5, 1, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2260
		rightHip.MaxVelocity = 0.1
2261
		rightHip.Name = "Right Hip"
2262
		rightHip.Part0 = torso
2263
		rightHip.Part1 = rightLeg
2264
		rightShoulder.C0 = CFrame.new(1, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2265
		rightShoulder.C1 = CFrame.new(-0.5, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
2266
		rightShoulder.MaxVelocity = 0.15
2267
		rightShoulder.Name = "Right Shoulder"
2268
		rightShoulder.Part0 = torso
2269
		rightShoulder.Part1 = rightArm
2270
		if prevLeftHip then
2271
			leftHip.CurrentAngle = prevLeftHip.CurrentAngle
2272
			leftHip.DesiredAngle = prevLeftHip.DesiredAngle
2273
		end
2274
		if prevLeftShoulder then
2275
			leftShoulder.CurrentAngle = prevLeftShoulder.CurrentAngle
2276
			leftShoulder.DesiredAngle = prevLeftShoulder.DesiredAngle
2277
		end
2278
		if prevRightHip then
2279
			rightHip.CurrentAngle = prevRightHip.CurrentAngle
2280
			rightHip.DesiredAngle = prevRightHip.DesiredAngle
2281
		end
2282
		if prevRightShoulder then
2283
			rightShoulder.CurrentAngle = prevRightShoulder.CurrentAngle
2284
			rightShoulder.DesiredAngle = prevRightShoulder.DesiredAngle
2285
		end
2286
		neck.C0 = CFrame.new(0, 1, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
2287
		neck.C1 = CFrame.new(0, -0.5, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
2288
		neck.Name = "Neck"
2289
		neck.Part0 = torso
2290
		neck.Part1 = head
2291
		rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
2292
		rootJoint.C1 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
2293
		rootJoint.Name = "RootJoint"
2294
		rootJoint.Part0 = rootPart
2295
		rootJoint.Part1 = torso
2296
		feetPart.BottomSurface = "Smooth"
2297
		feetPart.CanCollide = false
2298
		feetPart.CFrame = torsoCFrame * CFrame.new(0, -3.1, 0)
2299
		feetPart.FormFactor = "Custom"
2300
		feetPart.Locked = true
2301
		feetPart.Name = "Platform"
2302
		feetPart.Size = Vector3.new(1.8, 0.2, 0.8)
2303
		feetPart.TopSurface = "Smooth"
2304
		feetPart.Transparency = 1
2305
		feetWeld.C0 = CFrame.new(0, -3, 0)
2306
		feetWeld.C1 = CFrame.new(0, 0.1, 0)
2307
		feetWeld.Name = "PlatformWeld"
2308
		feetWeld.Part0 = torso
2309
		feetWeld.Part1 = feetPart
2310
		table.insert(connections, feetPart.Touched:connect(function(hit)
2311
			feetTouching[hit] = true
2312
		end))
2313
		table.insert(connections, feetPart.TouchEnded:connect(function(hit)
2314
			feetTouching[hit] = nil
2315
		end))
2316
		feetTouchInterest = feetPart:FindFirstChild("TouchInterest")
2317
		bodyGyro.D = 3250
2318
		bodyGyro.P = 400000
2319
		bodyGyro.maxTorque = Vector3.new(1000000000, 0, 1000000000)
2320
		bodyVelocity.P = 5000
2321
		bodyVelocity.maxForce = Vector3.new(0, 0, 0)
2322
		bodyVelocity.velocity = Vector3.new(0, 0, 0)
2323
		torsoLight = Instance.new("PointLight", torso)
2324
		torsoLight.Brightness = 0.4
2325
		torsoLight.Color = Color3.new(1, 1, 1)
2326
		torsoLight.Range = 16
2327
		torsoLight.Shadows = true
2328
		local ff1, ff2, ff3, ff4, ff5, ff6, ff7, ff8, ff9 = Instance.new("ForceField", head), Instance.new("ForceField", leftArm), Instance.new
2329
2330
("ForceField", leftLeg), Instance.new("ForceField", rightArm), Instance.new("ForceField", rightLeg), Instance.new("ForceField", torso), Instance.new
2331
2332
("ForceField", wildcardHandle), Instance.new("ForceField", feetPart), Instance.new("ForceField", rootPart)
2333
		local forcefields = {[ff1] = head, [ff2] = leftArm, [ff3] = leftLeg, [ff4] = rightArm, [ff5] = rightLeg, [ff6] = torso, [ff7] = 
2334
2335
wildcardHandle, [ff8] = feetPart, [ff9] = rootPart}	
2336
		local objects = {[humanoid] = true, [head] = true, [leftArm] = true, [leftLeg] = true, [rightArm] = true, [rightLeg] = true, [torso] = true, 
2337
2338
[rootPart] = true, [rootJoint] = true, [soundFreeFalling] = true, [soundGettingUp] = true, [soundRunning] = true, [leftHip] = true, [leftShoulder] = true, 
2339
2340
[rightHip] = true, [rightShoulder] = true, [neck] = true, [feetPart] = true, [feetWeld] = true, [feetTouchInterest] = true, [bodyGyro] = true, 
2341
2342
[bodyVelocity] = true, [ff1] = true, [ff2] = true, [ff3] = true, [ff4] = true, [ff5] = true, [ff6] = true, [ff7] = true, [ff8] = true, [ff9] = true}		
2343
		local tshirtUrl = appearance.tshirt
2344
		if tshirtUrl then
2345
			local tshirt = Instance.new("Decal", torso)
2346
			tshirt.Name = "roblox"
2347
			tshirt.Texture = tshirtUrl
2348
			objects[tshirt] = true
2349
		end
2350
		for _, template in ipairs(appearance.characterObjects) do
2351
			local object = template:Clone()
2352
			local newObjects = {object}
2353
			for _, object in ipairs(newObjects) do
2354
				objects[object] = true
2355
				for _, child in ipairs(object:GetChildren()) do
2356
					table.insert(newObjects, child)
2357
				end				
2358
			end
2359
			if object:IsA("BodyColors") then
2360
				head.BrickColor = object.HeadColor
2361
				leftArm.BrickColor = object.LeftArmColor
2362
				leftLeg.BrickColor = object.LeftLegColor
2363
				rightArm.BrickColor = object.RightArmColor
2364
				rightLeg.BrickColor = object.RightLegColor
2365
				torso.BrickColor = object.TorsoColor
2366
			elseif object:IsA("Hat") then
2367
				local handle = object:FindFirstChild("Handle")
2368
				if handle and handle:IsA("BasePart") then
2369
					local weld = Instance.new("Weld", head)
2370
					weld.C0 = CFrame.new(0, 0.5, 0)
2371
					local attachmentPos = object.AttachmentPos
2372
					local attachmentRight = object.AttachmentRight
2373
					local attachmentUp = object.AttachmentUp
2374
					local attachmentForward = object.AttachmentForward
2375
					weld.C1 = CFrame.new(attachmentPos.X, attachmentPos.Y, attachmentPos.Z,
2376
										 attachmentRight.X, attachmentUp.X, -attachmentForward.X,
2377
										 attachmentRight.Y, attachmentUp.Y, -attachmentForward.Y,
2378
										 attachmentRight.Z, attachmentUp.Z, -attachmentForward.Z)
2379
					weld.Name = "HeadWeld"
2380
					weld.Part0 = head
2381
					weld.Part1 = handle
2382
					handle.Parent = model
2383
					local antiGravity = Instance.new("BodyForce", handle)
2384
					antiGravity.force = Vector3.new(0, handle:GetMass() * 196.2, 0)
2385
					objects[object] = false
2386
					object.Parent = nil
2387
					objects[weld] = true
2388
				end
2389
			end
2390
			object.Parent = model
2391
		end
2392
		local facePresent = false
2393
		local headMeshPresent = false
2394
		for _, template in ipairs(appearance.headObjects) do
2395
			local object = template:Clone()
2396
			local newObjects = {object}
2397
			for _, object in ipairs(newObjects) do
2398
				objects[object] = true
2399
				for _, child in ipairs(object:GetChildren()) do
2400
					table.insert(newObjects, child)
2401
				end				
2402
			end
2403
			if object:IsA("DataModelMesh") then
2404
				headMeshPresent = true
2405
			elseif object:IsA("Decal") then
2406
				facePresent = true
2407
			end
2408
			object.Parent = head
2409
		end
2410
		if not facePresent then
2411
			local face = Instance.new("Decal", head)
2412
			face.Texture = "rbxasset://textures/face.png"
2413
			objects[face] = true
2414
		end
2415
		if not headMeshPresent then
2416
			local headMesh = Instance.new("SpecialMesh", head)
2417
			headMesh.Scale = Vector3.new(1.25, 1.25, 1.25)
2418
			objects[headMesh] = true
2419
		end
2420
		table.insert(connections, model.DescendantAdded:connect(function(object)
2421
			local success, is_localscript = pcall(Game.IsA, object, "LocalScript")
2422
			if success and is_localscript then
2423
				pcall(Utility.SetProperty, object, "Disabled", true)
2424
				local changed_connection = pcall(object.Changed.connect, object.Changed, function(property)
2425
					if property == "Disabled" and not object.Disabled then
2426
						pcall(Utility.SetProperty, object, "Disabled", true)
2427
						Network.TransmitServer("(...):Destroy()", object)
2428
					end
2429
				end)
2430
			end
2431
			if not objects[object] then
2432
				Network.TransmitServer("(...):Destroy()", object)
2433
			end
2434
		end))
2435
		model.Parent = Workspace
2436
		Player.Character = model
2437
		Camera.CameraSubject = humanoid
2438
		Camera.CameraType = "Track"
2439
		Camera.CoordinateFrame = cameraCFrame
2440
		local IsStanding
2441
		local RegenerateHealth
2442
		local ResetCharacter
2443
		function IsStanding()
2444
			return not not next(feetTouching)
2445
		end
2446
		function RegenerateHealth()
2447
			if humanoid.Health < 1 then
2448
				humanoid.Health = 100
2449
			elseif not regeneratingHealth then
2450
				regeneratingHealth = true
2451
				local elapsedTime = wait(1)
2452
				regeneratingHealth = false
2453
				if humanoid.Health < 100 then
2454
					humanoid.Health = math.min(humanoid.Health + elapsedTime, 100)
2455
				end
2456
			end
2457
		end
2458
		function ResetCharacter()
2459
			for index, connection in ipairs(connections) do
2460
				connection:disconnect()
2461
			end
2462
			active = false
2463
		end
2464
		table.insert(connections, model.AncestryChanged:connect(ResetCharacter))
2465
		table.insert(connections, model.DescendantRemoving:connect(function(object)
2466
			local parent = forcefields[object]
2467
			if parent then
2468
				forcefields[object] = nil
2469
				local new_forcefield = Instance.new("ForceField")
2470
				forcefields[new_forcefield] = parent
2471
				objects[new_forcefield] = true
2472
				new_forcefield.Parent = parent
2473
			elseif objects[object] then
2474
				ResetCharacter()
2475
			end
2476
		end))
2477
		table.insert(connections, humanoid.HealthChanged:connect(RegenerateHealth))
2478
		table.insert(connections, humanoid.Climbing:connect(function() pose = "Climbing" end))
2479
		table.insert(connections, humanoid.FallingDown:connect(function(state)  pose = "FallingDown" end))
2480
		table.insert(connections, humanoid.FreeFalling:connect(function(state) pose = "FreeFall" if state then soundFreeFalling:Play() else 
2481
2482
soundFreeFalling:Pause() end end))
2483
		table.insert(connections, humanoid.GettingUp:connect(function(state) pose = "GettingUp" if state then soundGettingUp:Play() else 
2484
2485
soundGettingUp:Pause() end end))
2486
		table.insert(connections, humanoid.PlatformStanding:connect(function() pose = "PlatformStanding" end))
2487
		table.insert(connections, humanoid.Seated:connect(function() pose = "Seated" end))
2488
		table.insert(connections, humanoid.Swimming:connect(function(speed) if speed > 0 then pose = "Swimming" else pose = "Standing" end end))
2489
		local previousRootPartCFrame = rootPart.CFrame
2490
		TaskScheduler.Start(function()
2491
			while active do
2492
				local totalTime = TaskScheduler.GetCurrentTime()
2493
				local stepTime = 1 / 60
2494
				if not PlayerControl.characterEnabled then
2495
					ResetCharacter()
2496
					break
2497
				end
2498
				torsoLight.Brightness = 0.5 + 0.15 * math.sin(totalTime * 0.75 * math.pi)
2499
				local featherfallEnabled = PlayerControl.IsFeatherfallEnabled()
2500
				local rootPartCFrame = rootPart.CFrame
2501
				if not jumpDebounce and UserInterface.IsKeyDown(" ") then
2502
					if humanoid.Sit then
2503
						humanoid.Sit = false
2504
					end
2505
					if IsStanding() then
2506
						jumpDebounce = true
2507
						pose = "Jumping"
2508
						rootPart.Velocity = Vector3.new(rootPart.Velocity.X, 50, rootPart.Velocity.Z)
2509
						torso.Velocity = Vector3.new(torso.Velocity.X, 50, torso.Velocity.Z)						
2510
						TaskScheduler.Schedule(1, function()
2511
							if pose == "Jumping" then
2512
								pose = "FreeFall"
2513
							end
2514
							jumpDebounce = false
2515
							humanoid.Jump = false
2516
						end)
2517
					end
2518
				end
2519
				local cameraCFrame = Camera.CoordinateFrame
2520
				local cameraDirection = cameraCFrame.lookVector
2521
				if flying then
2522
					if PlayerControl.rolling then
2523
						local rootPartCFrame = rootPart.CFrame
2524
						local speed = (rootPartCFrame - rootPartCFrame.p):pointToObjectSpace(rootPart.Velocity).Y
2525
						local decay = 0.5 ^ stepTime
2526
						if math.abs(speed) <= 50 then
2527
							PlayerControl.rollingAngle = (((PlayerControl.rollingAngle + 0.5) % 1 - 0.5) * decay) % 1
2528
							PlayerControl.rollingOffset = PlayerControl.rollingOffset * decay
2529
						else
2530
							PlayerControl.rollingAngle = (PlayerControl.rollingAngle + stepTime * speed * 
2531
2532
PlayerControl.rollingSpeed) % 1
2533
							PlayerControl.rollingOffset = (PlayerControl.rollingOffset + PlayerControl.rollingMaxOffset * (1 / 
2534
2535
decay - 1)) * decay
2536
						end
2537
						rootJoint.C0 = (CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0) * CFrame.Angles(PlayerControl.rollingAngle * 
2538
2539
2 * math.pi, 0, 0)) * CFrame.new(0, -PlayerControl.rollingOffset, 0)
2540
					else
2541
						rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
2542
						PlayerControl.rollingAngle = 0
2543
						PlayerControl.rollingOffset = 0
2544
					end
2545
					rightShoulder.MaxVelocity = 0.5
2546
					leftShoulder.MaxVelocity = 0.5
2547
					rightShoulder.DesiredAngle = 0
2548
					leftShoulder.DesiredAngle = 0
2549
					rightHip.DesiredAngle = 0
2550
					leftHip.DesiredAngle = 0
2551
					bodyGyro.D = 500
2552
					bodyGyro.P = 1e6
2553
					bodyGyro.maxTorque = Vector3.new(1e6, 1e6, 1e6)
2554
					bodyVelocity.P = 1250
2555
					bodyVelocity.maxForce = Vector3.new(1e6, 1e6, 1e6)
2556
					local movementRight = 0
2557
					local movementForward = 0
2558
					local movementUp = 0
2559
					if UserInterface.IsKeyDown("a") and not UserInterface.IsKeyDown("d") then
2560
						movementRight = -1
2561
					elseif UserInterface.IsKeyDown("d") then
2562
						movementRight = 1
2563
					end
2564
					if UserInterface.IsKeyDown("w") then
2565
						movementUp = 0.2
2566
						if not UserInterface.IsKeyDown("s") then
2567
							movementForward = -1
2568
						end
2569
					elseif UserInterface.IsKeyDown("s") then
2570
						movementForward = 1
2571
					end
2572
					local movement = PlayerControl.fly_acceleration * cameraCFrame:vectorToWorldSpace(Vector3.new(movementRight, 
2573
2574
movmentUp, movementForward))
2575
					local previousMomentum = flyingMomentum
2576
					local previousTilt = flyingTilt
2577
					flyingMomentum = movement + flyingMomentum * (1 - PlayerControl.fly_acceleration / PlayerControl.fly_speed)
2578
					flyingTilt = ((flyingMomentum * Vector3.new(1, 0, 1)).unit:Cross((previousMomentum * Vector3.new(1, 0, 1)).unit)).Y
2579
					if flyingTilt ~= flyingTilt or flyingTilt == math.huge then
2580
						flyingTilt = 0
2581
					end
2582
					local absoluteTilt = math.abs(flyingTilt)
2583
					if absoluteTilt > 0.06 or absoluteTilt < 0.0001 then
2584
						if math.abs(previousTilt) > 0.0001 then
2585
							flyingTilt = previousTilt * 0.9
2586
						else
2587
							flyingTilt = 0
2588
						end
2589
					else
2590
						flyingTilt = previousTilt * 0.77 + flyingTilt * 0.25
2591
					end
2592
					previousTilt = flyingTilt
2593
					if flyingMomentum.magnitude < 0.1 then
2594
						flyingMomentum = Vector3.new(0, 0, 0)
2595
--						bodyGyro.cframe = cameraCFrame
2596
					else
2597
						local momentumOrientation = CFrame.new(Vector3.new(0, 0, 0), flyingMomentum)
2598
						local tiltOrientation = CFrame.Angles(0, 0, -20 * flyingTilt)
2599
						bodyGyro.cframe = momentumOrientation * tiltOrientation * CFrame.Angles(-0.5 * math.pi * math.min
2600
2601
(flyingMomentum.magnitude / PlayerControl.fly_speed, 1), 0, 0)
2602
					end
2603
					bodyVelocity.velocity = flyingMomentum + Vector3.new(0, 0.15695775618683547, 0)
2604
					rootPart.Velocity = flyingMomentum
2605
					previousMomentum = flyingMomentum
2606
				else
2607
					rootJoint.C0 = CFrame.new(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0)
2608
					PlayerControl.rollingAngle = 0
2609
					PlayerControl.rollingOffset = 0
2610
					bodyGyro.D = 3250
2611
					bodyGyro.P = 400000
2612
					bodyVelocity.P = 5000
2613
					local cameraDirection = cameraCFrame.lookVector
2614
					local walkDirection = Vector3.new(0, 0, 0)
2615
					local walkSpeed = 16
2616
					if UserInterface.IsKeyDown("w") or UserInterface.IsKeyDown("\17") then
2617
						if UserInterface.IsKeyDown("a") then
2618
							walkDirection = Vector3.new(cameraDirection.X + cameraDirection.Z, 0, cameraDirection.Z - 
2619
2620
cameraDirection.X).unit
2621
						elseif UserInterface.IsKeyDown("d") then
2622
							walkDirection = Vector3.new(cameraDirection.X - cameraDirection.Z, 0, cameraDirection.Z + 
2623
2624
cameraDirection.X).unit
2625
						else
2626
							walkDirection = Vector3.new(cameraDirection.X, 0, cameraDirection.Z).unit
2627
						end
2628
					elseif UserInterface.IsKeyDown("s") or UserInterface.IsKeyDown("\18") then
2629
						if UserInterface.IsKeyDown("a") then
2630
							walkDirection = Vector3.new(-cameraDirection.X + cameraDirection.Z, 0, -cameraDirection.Z - 
2631
2632
cameraDirection.X).unit
2633
						elseif UserInterface.IsKeyDown("d") then
2634
							walkDirection = Vector3.new(-cameraDirection.X - cameraDirection.Z, 0, -cameraDirection.Z + 
2635
2636
cameraDirection.X).unit
2637
						else
2638
							walkDirection = Vector3.new(-cameraDirection.X, 0, -cameraDirection.Z).unit
2639
						end
2640
					elseif UserInterface.IsKeyDown("a") then
2641
						walkDirection = Vector3.new(cameraDirection.Z, 0, -cameraDirection.X).unit
2642
					elseif UserInterface.IsKeyDown("d") then
2643
						walkDirection = Vector3.new(-cameraDirection.Z, 0, cameraDirection.X).unit
2644
					else
2645
						walkSpeed = 0
2646
					end
2647
					if walkSpeed ~= previousWalkSpeed then
2648
						if walkSpeed > 0 then
2649
							soundRunning:Play()
2650
						else
2651
							soundRunning:Pause()
2652
						end
2653
					end
2654
					if walkSpeed > 0 then
2655
						if pose ~= "Jumping" then
2656
							if IsStanding() then
2657
								pose = "Running"
2658
							else
2659
								pose = "FreeFall"
2660
							end
2661
						end
2662
						bodyGyro.cframe = CFrame.new(Vector3.new(), walkDirection)
2663
						bodyGyro.maxTorque = Vector3.new(1000000000, 1000000000, 1000000000)
2664
						bodyVelocity.maxForce = Vector3.new(1000000, maxForceY, 1000000)
2665
					else
2666
						if pose ~= "Jumping" then
2667
							if IsStanding() then
2668
								pose = "Standing"
2669
							else
2670
								pose = "FreeFall"
2671
							end
2672
						end
2673
						-- TODO: find and fix bug that causes torso to rotate back to some angle
2674
						bodyGyro.maxTorque = Vector3.new(1000000000, 1000000000, 1000000000) -- Vector3.new(1000000000, 0, 
2675
2676
1000000000)
2677
						if PlayerControl.pushable then
2678
							bodyVelocity.maxForce = Vector3.new(0, 0, 0)
2679
						else
2680
							bodyVelocity.maxForce = Vector3.new(1000000, 0, 1000000)
2681
						end
2682
					end
2683
					if featherfallEnabled then
2684
						local velocity = rootPart.Velocity
2685
						if velocity.Y > 50 then
2686
							rootPart.Velocity = Vector3.new(velocity.X, 50, velocity.Z)
2687
						elseif velocity.Y < -50 then
2688
							rootPart.Velocity = Vector3.new(velocity.X, -50, velocity.Z)
2689
						end
2690
						local distanceVector = rootPartCFrame.p - previousRootPartCFrame.p
2691
						local offsetX, offsetY, offsetZ = distanceVector.X, distanceVector.Y, distanceVector.Z
2692
						local MAX_MOVEMENT = 50 * 0.03333333507180214
2693
						if offsetX > MAX_MOVEMENT then
2694
							offsetX = MAX_MOVEMENT
2695
						elseif offsetX < -MAX_MOVEMENT then
2696
							offsetX = -MAX_MOVEMENT
2697
						end
2698
						if offsetY > MAX_MOVEMENT then
2699
							offsetY = MAX_MOVEMENT
2700
						elseif offsetY < -MAX_MOVEMENT then
2701
							offsetY = -MAX_MOVEMENT
2702
						end
2703
						if offsetZ > MAX_MOVEMENT then
2704
							offsetZ = MAX_MOVEMENT
2705
						elseif offsetZ < -MAX_MOVEMENT then
2706
							offsetZ = -MAX_MOVEMENT
2707
						end
2708
						local offset = Vector3.new(offsetX, offsetY, offsetZ)
2709
						if offset ~= distanceVector then
2710
							rootPartCFrame = previousRootPartCFrame + offset
2711
							--rootPart.CFrame = rootPartCFrame
2712
						end
2713
					end
2714
					local walkingVelocity = walkDirection * walkSpeed
2715
					bodyVelocity.velocity = walkingVelocity
2716
					if not jumpDebounce and math.abs(rootPart.Velocity.Y) <= 0.1 then
2717
						rootPart.Velocity = Vector3.new(walkingVelocity.X, rootPart.Velocity.Y, walkingVelocity.Z)
2718
					end
2719
					previousWalkSpeed = walkSpeed
2720
					if pose == "Jumping" or jumpDebounce then
2721
						rightShoulder.MaxVelocity = 0.5
2722
						leftShoulder.MaxVelocity = 0.5
2723
						rightShoulder.DesiredAngle = 3.14
2724
						leftShoulder.DesiredAngle = -3.14
2725
						rightHip.DesiredAngle = 0
2726
						leftHip.DesiredAngle = 0
2727
					elseif pose == "FreeFall" then
2728
						rightShoulder.MaxVelocity = 0.5
2729
						leftShoulder.MaxVelocity = 0.5
2730
						rightShoulder.DesiredAngle = 3.14
2731
						leftShoulder.DesiredAngle = -3.14
2732
						rightHip.DesiredAngle = 0
2733
						leftHip.DesiredAngle = 0
2734
					elseif pose == "Seated" then
2735
						rightShoulder.MaxVelocity = 0.15
2736
						leftShoulder.MaxVelocity = 0.15
2737
						rightShoulder.DesiredAngle = 3.14 / 2
2738
						leftShoulder.DesiredAngle = -3.14 / 2
2739
						rightHip.DesiredAngle = 3.14 / 2
2740
						leftHip.DesiredAngle = -3.14 / 2
2741
					else
2742
						local climbFudge = 0
2743
						local amplitude
2744
						local frequency
2745
						if pose == "Running" then
2746
							rightShoulder.MaxVelocity = 0.15
2747
							leftShoulder.MaxVelocity = 0.15
2748
							amplitude = 1
2749
							frequency = 9
2750
						elseif (pose == "Climbing") then
2751
							rightShoulder.MaxVelocity = 0.5 
2752
							leftShoulder.MaxVelocity = 0.5
2753
							amplitude = 1
2754
							frequency = 9
2755
							climbFudge = 3.14
2756
						else
2757
							amplitude = 0.1
2758
							frequency = 1
2759
						end
2760
						local desiredAngle = amplitude * math.sin(totalTime * frequency)
2761
						rightShoulder.DesiredAngle = desiredAngle + climbFudge
2762
						leftShoulder.DesiredAngle = desiredAngle - climbFudge
2763
						rightHip.DesiredAngle = -desiredAngle
2764
						leftHip.DesiredAngle = -desiredAngle
2765
					end
2766
				end
2767
				previousRootPartCFrame = rootPartCFrame
2768
				RunService.RenderStepped:wait()
2769
			end
2770
			if model.Parent ~= nil then
2771
				model.Parent = nil
2772
			end
2773
			PlayerControl.CreateCharacter()
2774
		end)
2775
		humanoid.Health = 100
2776
		character = model
2777
		Network.TransmitServer("chatAdornee = ...", head)
2778
	elseif characterMode == "pyramid" then
2779
		if PlayerControl.characterEnabled then
2780
			Camera.CameraType = "Fixed"
2781
			PyramidCharacter.camera_distance = (Camera.Focus.p - Camera.CoordinateFrame.p).magnitude
2782
			PyramidCharacter.camera_position = Camera.Focus.p
2783
			PyramidCharacter.Teleport(Camera.Focus.p)
2784
			PyramidCharacter.visible = true
2785
			Player.Character = nil
2786
		else
2787
			PyramidCharacter.visible = false
2788
		end
2789
	end
2790
end
2791
function PlayerControl.GetCharacter()
2792
	return character
2793
end
2794
function PlayerControl.GetHead()
2795
	local characterMode = PlayerControl.characterMode
2796
	if characterMode == "normal" then
2797
		return head
2798
	elseif characterMode == "pyramid" then
2799
		return PyramidCharacter.core
2800
	end
2801
end
2802
function PlayerControl.GetHumanoid()
2803
	return humanoid
2804
end
2805
function PlayerControl.GetRootPart()
2806
	return rootPart
2807
end
2808
function PlayerControl.GetTorso()
2809
	return torso
2810
end
2811
function PlayerControl.IsEnabled()
2812
	return PlayerControl.characterEnabled
2813
end
2814
function PlayerControl.IsFeatherfallEnabled()
2815
	return PlayerControl.featherfallEnabled
2816
end
2817
function PlayerControl.IsPushable()
2818
	return PlayerControl.pushable
2819
end
2820
function PlayerControl.IsRolling()
2821
	return PlayerControl.rolling
2822
end
2823
function PlayerControl.ResetCharacter()
2824
	if character and character.Parent then
2825
		character.Parent = nil
2826
	end
2827
	PyramidCharacter.visible = false
2828
end
2829
function PlayerControl.SetEnabled(state, no_animation)
2830
	state = not not state
2831
	if state ~= PlayerControl.characterEnabled then
2832
		PlayerControl.characterEnabled = state
2833
		local characterMode = PlayerControl.characterMode
2834
		if characterMode == "normal" then
2835
			local torso = PlayerControl.GetRootPart()
2836
			local rootPart = PlayerControl.GetRootPart()
2837
			if rootPart then
2838
				if PlayerControl.characterEnabled then
2839
					local torso_cframe = Camera.Focus:toWorldSpace(PlayerControl.hide_torso_object_cframe)
2840
					PlayerControl.torso_cframe = torso_cframe
2841
					torso.CFrame = torso_cframe
2842
					rootPart.CFrame = torso_cframe
2843
				else
2844
					PlayerControl.hide_torso_object_cframe = Camera.Focus:toObjectSpace(rootPart.CFrame)
2845
				end
2846
			else
2847
				PlayerControl.torso_cframe = Camera.Focus
2848
			end
2849
			if PlayerControl.characterEnabled then
2850
				PlayerControl.CreateCharacter()
2851
				RunService.Stepped:wait()
2852
				coroutine.yield()
2853
				if not no_animation then
2854
					Network.TransmitServer("GraphicalEffects.CrystalRing({base_part = (...), crystal_color = BrickColor.new
2855
2856
(\"Institutional white\"), float_duration = 2})", PlayerControl.GetTorso())
2857
				end		
2858
			else
2859
				Player.Character = nil
2860
				Camera.CameraType = "Fixed"
2861
				if not no_animation then
2862
					Network.TransmitServer("GraphicalEffects.CrystalRing({position = (...), crystal_color = BrickColor.new
2863
2864
(\"Institutional white\"), float_duration = 2})", PlayerControl.GetTorso().Position)
2865
				end
2866
			end
2867
		else
2868
			if state then
2869
				PlayerControl.CreateCharacter()
2870
				RunService.Stepped:wait()
2871
				coroutine.yield()
2872
				if not no_animation then
2873
					Network.TransmitServer("GraphicalEffects.CrystalRing({base_part = (...), crystal_color = BrickColor.new
2874
2875
(\"Institutional white\"), float_duration = 2})", PyramidCharacter.core)
2876
				end
2877
			else
2878
				PyramidCharacter.visible = false
2879
				if not no_animation then
2880
					Network.TransmitServer("GraphicalEffects.CrystalRing({position = (...), crystal_color = BrickColor.new
2881
2882
(\"Institutional white\"), float_duration = 2})", PyramidCharacter.core.Position)
2883
				end
2884
			end
2885
		end
2886
	end
2887
end
2888
function PlayerControl.SetFeatherfallEnabled(state)
2889
	state = not not state
2890
	if state ~= PlayerControl.featherfallEnabled then
2891
		PlayerControl.featherfallEnabled = state
2892
		if state then
2893
			Logger.print("Info", "Featherfall enabled in PlayerControl")
2894
		else
2895
			Logger.print("Info", "Featherfall disabled in PlayerControl")
2896
		end
2897
	end
2898
end
2899
function PlayerControl.SetPushable(state)
2900
	state = not not state
2901
	if state ~= PlayerControl.pushable then
2902
		PlayerControl.pushable = state
2903
		if state then
2904
			Logger.print("Info", "Pushing enabled in PlayerControl")
2905
		else
2906
			Logger.print("Info", "Pushing disabled in PlayerControl")
2907
		end
2908
	end
2909
end
2910
function PlayerControl.SetRolling(state)
2911
	state = not not state
2912
	if state ~= PlayerControl.rolling then
2913
		PlayerControl.rolling = state
2914
		if state then
2915
			Logger.print("Info", "Rolling fly mode enabled in PlayerControl")
2916
		else
2917
			Logger.print("Info", "Rolling fly mode disabled in PlayerControl")
2918
		end
2919
	end
2920
end
2921
function PlayerControl.StartFlying()
2922
	PlayerControl.fly_speed = PlayerControl.fly_basespeed
2923
	if torso then
2924
		flyingMomentum = torso.Velocity + torso.CFrame.lookVector * 3 + Vector3.new(0, 10, 0)
2925
	else
2926
		flyingMomentum = Vector3.new()
2927
	end
2928
	flyingTilt = 0
2929
	flying = true
2930
end
2931
function PlayerControl.StopFlying()
2932
	if bodyGyro.cframe then
2933
		local lookVector = bodyGyro.cframe.lookVector
2934
		if lookVector.X ~= 0 or lookVector.Z ~= 0 then
2935
			bodyGyro.cframe = CFrame.new(Vector3.new(), Vector3.new(lookVector.X, 0, lookVector.Z))
2936
		end
2937
	end
2938
	flying = false
2939
end
2940
local previousTime = 0
2941
UserInterface.SetHotkey(" ", function()
2942
	if flying then
2943
		PlayerControl.StopFlying()
2944
	else
2945
		local currentTime = time()
2946
		if currentTime - previousTime < 0.4 then
2947
			previousTime = 0
2948
			PlayerControl.StartFlying()
2949
		else
2950
			previousTime = currentTime
2951
		end
2952
	end
2953
end)
2954
]])
2955
Module.Create("RBXInstance", [[
2956
RBXInstance.init_metatable = {}
2957
function RBXInstance.init_metatable:__call(data)
2958
	local instance = Instance.new(self[1])
2959
	for key, value in pairs(data) do
2960
		if type(key) == "number" then
2961
			value.Parent = instance
2962
		else
2963
			instance[key] = value
2964
		end
2965
	end
2966
	return instance
2967
end
2968
function RBXInstance.new(className)
2969
	return setmetatable({className}, RBXInstance.init_metatable)
2970
end
2971
]])
2972
Module.Create("AdvancedGUI", [=[
2973
if not AdvancedGUI.GUI_BASE_COLOR then
2974
	AdvancedGUI.GUI_BASE_COLOR = Color3.new(0, 0, 0)
2975
end
2976
function AdvancedGUI.GenerateChatColor(speakerName)
2977
	local chatColor = ChatColor.Get(speakerName).Color
2978
	local brightness = chatColor.r + chatColor.g + chatColor.b
2979
	if brightness < 1.5 then
2980
		chatColor = Color3.new(math.min(1, 0.4 + chatColor.r), math.min(1, 0.4 + chatColor.g), math.min(1, 0.4 + chatColor.b))
2981
	else
2982
		chatColor = Color3.new(math.min(1, 0.05 + chatColor.r), math.min(1, 0.05 + chatColor.g), math.min(1, 0.05 + chatColor.b))
2983
	end
2984
	return chatColor
2985
end
2986
GuiBase = {}
2987
GuiBase.__index = GuiBase
2988
function GuiBase:new(data)
2989
	local instance = setmetatable({}, self)
2990
	instance:Init(data)
2991
	return instance
2992
end
2993
function GuiBase:Destroy()
2994
	if self.parent then
2995
		self.parent.children[self] = nil
2996
	end
2997
	for child in pairs(self.children) do
2998
		child:Destroy()
2999
	end
3000
	self.m_base_instance:Destroy()
3001
end
3002
function GuiBase:GetContentInstance(child)
3003
	return self.m_base_instance
3004
end
3005
function GuiBase:Init()
3006
	self.children = {}
3007
end
3008
function GuiBase:IsA(className)
3009
	return className == "GuiBase"
3010
end
3011
function GuiBase:SetParent(parent)
3012
	if parent ~= self.parent then
3013
		if self.parent then
3014
			self.parent.children[self] = nil
3015
		end
3016
		self.parent = parent
3017
		if parent then
3018
			parent.children[self] = true
3019
			self.m_base_instance.Parent = parent:GetContentInstance()
3020
		else
3021
			self.m_base_instance.Parent = nil
3022
		end
3023
	end
3024
end
3025
GuiObject = setmetatable({}, GuiBase)
3026
GuiObject.__index = GuiObject
3027
function GuiObject:Destroy()
3028
	self.DragBegin:disconnect()
3029
	self.DragMove:disconnect()
3030
	self.DragStopped:disconnect()
3031
	self.MouseButton1Click:disconnect()
3032
	self.MouseButton1Down:disconnect()
3033
	self.MouseButton1Up:disconnect()
3034
	self.MouseButton2Down:disconnect()
3035
	self.MouseButton2Up:disconnect()
3036
	self.MouseEnter:disconnect()
3037
	self.MouseLeave:disconnect()
3038
	GuiBase.Destroy(self)
3039
end
3040
function GuiObject:GetAbsolutePosition()
3041
	return self.m_base_instance.AbsolutePosition
3042
end
3043
function GuiObject:GetAbsoluteSize()
3044
	return self.m_base_instance.AbsoluteSize
3045
end
3046
function GuiObject:GetPosition()
3047
	return self.position
3048
end
3049
function GuiObject:GetSize()
3050
	return self.size
3051
end
3052
function GuiObject:Init()
3053
	GuiBase.Init(self)
3054
	self.mouseDown = false
3055
	self.mouseOver = false
3056
	self.DragBegin = RbxUtility.CreateSignal()
3057
	self.DragMove = RbxUtility.CreateSignal()
3058
	self.DragStopped = RbxUtility.CreateSignal()
3059
	self.MouseButton1Click = RbxUtility.CreateSignal()
3060
	self.MouseButton1Down = RbxUtility.CreateSignal()
3061
	self.MouseButton1Up = RbxUtility.CreateSignal()
3062
	self.MouseButton2Down = RbxUtility.CreateSignal()
3063
	self.MouseButton2Up = RbxUtility.CreateSignal()
3064
	self.MouseEnter = RbxUtility.CreateSignal()
3065
	self.MouseLeave = RbxUtility.CreateSignal()
3066
end
3067
function GuiObject:IsA(className)
3068
	return className == "GuiObject" or GuiBase.IsA(self, className)
3069
end
3070
function GuiObject:SetActive(active)
3071
	if active ~= self.active then
3072
		self.active = active
3073
	end
3074
end
3075
function GuiObject:SetBackgroundTransparency(backgroundTransparency)
3076
	if backgroundTransparency ~= self.backgroundTransparency then
3077
		self.backgroundTransparency = backgroundTransparency
3078
		self.m_base_instance.BackgroundTransparency = backgroundTransparency
3079
	end
3080
end
3081
function GuiObject:SetColor(color)
3082
	if color ~= self.color then
3083
		self.color = color
3084
		self.m_base_instance.BackgroundColor3 = color
3085
	end
3086
end
3087
function GuiObject:SetPosition(position)
3088
	if position ~= self.position then
3089
		self.position = position
3090
		self.m_base_instance.Position = position
3091
	end
3092
end
3093
function GuiObject:SetSize(size)
3094
	if size ~= self.size then
3095
		self.size = size
3096
		self.m_base_instance.Size = size
3097
	end
3098
end
3099
function GuiObject:SetVisible(visible)
3100
	if visible ~= self.visible then
3101
		self.visible = visible
3102
		self.m_base_instance.Visible = visible
3103
	end
3104
end
3105
function GuiObject:SetZIndex(zIndex)
3106
	local stack = {self.m_base_instance}
3107
	repeat
3108
		local object = stack[#stack]
3109
		stack[#stack] = nil
3110
		for _, child in ipairs(object:GetChildren()) do
3111
			stack[#stack + 1] = child
3112
		end
3113
		object.ZIndex = zIndex
3114
	until #stack == 0
3115
end
3116
GuiServiceClass = setmetatable({}, GuiBase)
3117
GuiServiceClass.__index = GuiServiceClass
3118
function GuiServiceClass:CreateTextArea(text, font, fontSize, textColor3, textXAlignment, textYAlignment, maxWidth, minWidth)
3119
	local totalHeight = 0
3120
	local frame = Instance.new("Frame")
3121
	frame.BackgroundTransparency = 1
3122
	local label = Instance.new("TextLabel")
3123
	label.BackgroundTransparency = 1
3124
	label.Font = font
3125
	label.FontSize = fontSize
3126
	label.TextColor3 = textColor3
3127
	label.TextTransparency = 1
3128
	label.TextWrapped = true
3129
	label.TextXAlignment = textXAlignment
3130
	label.TextYAlignment = textYAlignment
3131
	label.Parent = self.guiFrame
3132
	local index = 1
3133
	while true do
3134
		local length = #text - index + 1
3135
		if length > 1024 then
3136
			length = 1024
3137
			local textBlock = string.sub(text, index, index + length - 1)
3138
			label.Text = textBlock
3139
			local height = 0
3140
			local width = maxWidth
3141
			repeat
3142
				height = height + 20
3143
				label.Size = UDim2.new(0, width, 0, height)
3144
			until label.TextFits
3145
			repeat
3146
				height = height - 1
3147
				label.Size = UDim2.new(0, width, 0, height)
3148
			until not label.TextFits
3149
			repeat
3150
				length = length - 10
3151
				label.Text = string.sub(text, index, index + length - 1)
3152
			until label.TextFits
3153
			repeat
3154
				length = length + 1
3155
				label.Text = string.sub(text, index, index + length - 1)
3156
			until not label.TextFits
3157
			local overflowCharacter = string.sub(text, index + length - 1, index + length - 1)
3158
			length = length - 1
3159
			label.Text = string.sub(text, index, index + length - 1)
3160
			if overflowCharacter == "\n" then
3161
				index = index + 1
3162
			end
3163
			repeat
3164
				height = height - 1
3165
				label.Size = UDim2.new(0, width, 0, height)
3166
			until not label.TextFits
3167
			height = height + 1
3168
			local blockLabel = label:Clone()
3169
			blockLabel.Position = UDim2.new(0, 0, 0, totalHeight)
3170
			blockLabel.Size = UDim2.new(1, 0, 0, height)
3171
			blockLabel.Parent = frame
3172
			totalHeight = totalHeight + height
3173
			index = index + length
3174
		else
3175
			local textBlock = string.sub(text, index)
3176
			label.Text = textBlock
3177
			local height = 0
3178
			local width = maxWidth
3179
			repeat
3180
				height = height + 20
3181
				label.Size = UDim2.new(0, width, 0, height)
3182
			until label.TextFits
3183
			repeat
3184
				height = height - 1
3185
				label.Size = UDim2.new(0, width, 0, height)
3186
			until not label.TextFits
3187
			height = height + 1
3188
			if index == 1 then
3189
				repeat
3190
					width =  width - 10
3191
					label.Size = UDim2.new(0, width, 0, height)
3192
				until width < minWidth or not label.TextFits
3193
				width = math.max(width, minWidth - 1)
3194
				repeat
3195
					width =  width + 1
3196
					label.Size = UDim2.new(0, width, 0, height)
3197
				until label.TextFits
3198
			end
3199
			local blockLabel = label:Clone()
3200
			blockLabel.Position = UDim2.new(0, 0, 0, totalHeight)
3201
			blockLabel.Size = UDim2.new(1, 0, 0, height)
3202
			blockLabel.Parent = frame
3203
			label:Destroy()
3204
			frame.Size = UDim2.new(0, width, 0, totalHeight + height)
3205
			return frame
3206
		end
3207
	end
3208
end
3209
function GuiServiceClass:Destroy()
3210
	self.running = false
3211
	self.cameraPart:Destroy()
3212
	self.cameraConnection:disconnect()
3213
	self.keyDownConnection:disconnect()
3214
	self.mouseButton1DownConnection:disconnect()
3215
	self.mouseButton1UpConnection:disconnect()
3216
	self.mouseButton2DownConnection:disconnect()
3217
	self.mouseButton2UpConnection:disconnect()
3218
	self.mouseMoveConnection:disconnect()
3219
	self.steppedConnection:disconnect()
3220
end
3221
function GuiServiceClass:GetMousePosition()
3222
	local mouse = self.mouse
3223
	return mouse.X, mouse.Y -- mouse.X, mouse.Y + 2 -- return mouse.X - 2, mouse.Y - 3
3224
end
3225
function GuiServiceClass:GetTextBounds(text, font, fontSize, alignX, alignY, width)
3226
	local tempLabel = self.tempLabel
3227
	tempLabel.Font = font
3228
	tempLabel.FontSize = fontSize
3229
	tempLabel.Size = UDim2.new(0, width, 0, 4096)
3230
	tempLabel.Text = text
3231
	tempLabel.TextXAlignment = alignX
3232
	tempLabel.TextYAlignment = alignY
3233
	local textBounds = tempLabel.TextBounds
3234
	tempLabel.Text = ""
3235
	return textBounds
3236
end
3237
function GuiServiceClass:Init(data)
3238
	GuiBase.Init(self)
3239
	local _ = string.char
3240
	local camera = data.Camera
3241
	local mouse = data.Mouse
3242
	local cameraPart = Instance.new("Part")
3243
	local billboardGui = Instance.new("BillboardGui", cameraPart)
3244
	guiFrame = Instance.new("Frame", billboardGui)
3245
	cameraPart.Anchored = true
3246
	cameraPart.BottomSurface = "Smooth"
3247
	cameraPart.CanCollide = false
3248
--	cameraPart.CFrame = CFrame.new(16384, 16384, 16384)
3249
	cameraPart.FormFactor = "Custom"
3250
	cameraPart.Locked = true
3251
	cameraPart.Size = Vector3.new(0.2, 0.2, 0.2)
3252
	cameraPart.TopSurface = "Smooth"
3253
	cameraPart.Transparency = 1
3254
	billboardGui.Adornee = cameraPart
3255
	billboardGui.AlwaysOnTop = true
3256
--	billboardGui.ExtentsOffset = Vector3.new(-16384, -16384, -16384)
3257
	guiFrame.BackgroundTransparency = 1
3258
	cameraPart.Parent = camera
3259
	self.running = true
3260
	self.m_base_instance = guiFrame
3261
	self.billboardGui = billboardGui
3262
	self.cameraPart = cameraPart
3263
	self.tempLabel = RBXInstance.new "TextLabel" {
3264
		BackgroundTransparency = 1,
3265
		TextTransparency = 1,
3266
		TextWrapped = true,
3267
		Parent = guiFrame
3268
	}
3269
	self.mnemonics = {}
3270
	self.visible = true
3271
	self.camera = camera
3272
	self.mouse = mouse
3273
	self.cameraConnection = camera.Changed:connect(function(property)
3274
		self:UpdateView()
3275
		if property == "CameraType" then
3276
			if camera.CameraType ~= Enum.CameraType.Track and camera.CameraType ~= Enum.CameraType.Fixed then
3277
				camera.CameraType = Enum.CameraType.Track
3278
			end
3279
		elseif property == "CoordinateFrame" and camera.CameraType ~= Enum.CameraType.Fixed then
3280
			local cframe, focus = camera.CoordinateFrame, camera.Focus
3281
			local watchOffset = focus.p - cframe.p
3282
			local error = watchOffset.unit - cframe.lookVector
3283
			if error.magnitude >= 1e-3 then
3284
				local head = PlayerControl.GetHead()
3285
				local time1, velocity1
3286
				if head then
3287
					time1 = time()
3288
					velocity1 = head.Velocity
3289
				end
3290
				if camera.Changed:wait() == "CoordinateFrame" then
3291
					local position = cframe.p
3292
					if head then
3293
						local time2 = time()
3294
						local velocity2 = head.Velocity
3295
						position = position + 0.5 * (velocity1 + velocity2) * (time2 - time1)
3296
					end
3297
					camera.CoordinateFrame = CFrame.new(position, camera.Focus.p)
3298
				end
3299
			end
3300
		end
3301
	end)
3302
	self.keyDownConnection = mouse.KeyDown:connect(function(key) self:KeyDown(key) end)
3303
	self.mouseButton1DownConnection = mouse.Button1Down:connect(function() self:MouseButton1Down() end)
3304
	self.mouseButton1UpConnection = mouse.Button1Up:connect(function() self:MouseButton1Up() end)
3305
	self.mouseButton2DownConnection = mouse.Button2Down:connect(function() self:MouseButton2Down() end)
3306
	self.mouseButton2UpConnection = mouse.Button2Up:connect(function() self:MouseButton2Up() end)
3307
	self.mouseMoveConnection = mouse.Move:connect(function() self:MouseMove() end)
3308
	self.steppedConnection = RunService.RenderStepped:connect(function() self:UpdateObjects() self:UpdateView() end)
3309
	self.mousePreviousPosition = Vector2.new(self:GetMousePosition())
3310
end
3311
function GuiServiceClass:IsA(className)
3312
	return className == "GuiService" or GuiBase.IsA(self, className)
3313
end
3314
function GuiServiceClass:KeyDown(key)
3315
	local mnemonicButton = self.mnemonics[string.upper(key)]
3316
	if mnemonicButton then
3317
		mnemonicButton.Activated:fire()
3318
	end
3319
end
3320
function GuiServiceClass:MouseButton1Down()
3321
	local mouse = self.mouse
3322
	local mouseX, mouseY = self:GetMousePosition()
3323
	local stack = {self}
3324
	local dragObjects = {}
3325
	self.dragObjects = dragObjects
3326
	while #stack > 0 do
3327
		local object = stack[#stack]
3328
		stack[#stack] = nil
3329
		if object.visible then
3330
			for child in pairs(object.children) do
3331
				stack[#stack + 1] = child
3332
			end
3333
			if object.active then
3334
				local position = object:GetAbsolutePosition()
3335
				local size = object:GetAbsoluteSize()
3336
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
3337
					object.mouseDown = true
3338
					dragObjects[object] = true
3339
					local mouseButton1Down = object.MouseButton1Down
3340
					if mouseButton1Down then
3341
						mouseButton1Down:fire()
3342
						if object.autoButtonColor then
3343
							local color = object.color
3344
							local transparency = object.backgroundTransparency
3345
							object.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min(color.g + 
3346
3347
0.3, 1), math.min(color.b + 0.3, 1))
3348
							object.m_base_instance.BackgroundTransparency = transparency
3349
						end
3350
					end
3351
					object.DragBegin:fire()
3352
				end
3353
			end
3354
		end
3355
	end
3356
	self.mousePreviousPosition = Vector2.new(mouseX, mouseY)
3357
end
3358
function GuiServiceClass:MouseButton1Up()
3359
	local mouse = self.mouse
3360
	local mouseX, mouseY = self:GetMousePosition()
3361
	local stack = {self}
3362
	while #stack > 0 do
3363
		local object = stack[#stack]
3364
		stack[#stack] = nil
3365
		if object.visible then
3366
			for child in pairs(object.children) do
3367
				stack[#stack + 1] = child
3368
			end
3369
			if object.active then
3370
				local position = object:GetAbsolutePosition()
3371
				local size = object:GetAbsoluteSize()
3372
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
3373
					object.MouseButton1Up:fire()
3374
				end
3375
			end
3376
		end
3377
	end
3378
	local dragObjects = self.dragObjects
3379
	self.dragObjects = nil
3380
	if dragObjects then
3381
		for dragObject in pairs(dragObjects) do
3382
			dragObject.mouseDown = false
3383
			local position = dragObject:GetAbsolutePosition()
3384
			local size = dragObject:GetAbsoluteSize()
3385
			if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
3386
				dragObject.MouseButton1Click:fire()
3387
				local activated = dragObject.Activated
3388
				if activated then
3389
					activated:fire()
3390
				end
3391
			end
3392
			dragObject.DragStopped:fire()
3393
			if dragObject.autoButtonColor then
3394
				if dragObject.mouseOver then
3395
					local color = dragObject.color
3396
					local transparency = dragObject.backgroundTransparency
3397
					dragObject.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max(color.g - 0.3, 0), 
3398
3399
math.max(color.b - 0.3, 0))
3400
					dragObject.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.2)
3401
				else
3402
					dragObject.m_base_instance.BackgroundColor3 = dragObject.color
3403
					dragObject.m_base_instance.BackgroundTransparency = dragObject.backgroundTransparency
3404
				end
3405
			end
3406
			self.dragObject = nil
3407
		end
3408
	end
3409
end
3410
function GuiServiceClass:MouseButton2Down()
3411
	local mouse = self.mouse
3412
	local mouseX, mouseY = self:GetMousePosition()
3413
	local stack = {self}
3414
	while #stack > 0 do
3415
		local object = stack[#stack]
3416
		stack[#stack] = nil
3417
		if object.visible then
3418
			for child in pairs(object.children) do
3419
				stack[#stack + 1] = child
3420
			end
3421
			if object.active then
3422
				local position = object:GetAbsolutePosition()
3423
				local size = object:GetAbsoluteSize()
3424
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
3425
					local mouseButton2Down = object.MouseButton2Down
3426
					if mouseButton2Down then
3427
						mouseButton2Down:fire()
3428
					end
3429
				end
3430
			end
3431
		end
3432
	end
3433
	self.mousePreviousPosition = Vector2.new(mouseX, mouseY)
3434
end
3435
function GuiServiceClass:MouseButton2Up()
3436
	local mouse = self.mouse
3437
	local mouseX, mouseY = self:GetMousePosition()
3438
	local stack = {self}
3439
	while #stack > 0 do
3440
		local object = stack[#stack]
3441
		stack[#stack] = nil
3442
		if object.visible then
3443
			for child in pairs(object.children) do
3444
				stack[#stack + 1] = child
3445
			end
3446
			if object.active then
3447
				local position = object:GetAbsolutePosition()
3448
				local size = object:GetAbsoluteSize()
3449
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
3450
					local mouseButton2Up = object.MouseButton2Up
3451
					if mouseButton2Up then
3452
						mouseButton2Up:fire()
3453
					end
3454
				end
3455
			end
3456
		end
3457
	end
3458
end
3459
function GuiServiceClass:MouseMove()
3460
	self:UpdateObjects()
3461
	local dragObjects = self.dragObjects
3462
	if dragObjects then
3463
		for dragObject in pairs(dragObjects) do
3464
			local mouse = self.mouse
3465
			local mousePosition = Vector2.new(self:GetMousePosition())
3466
			dragObject.DragMove:fire(mousePosition - self.mousePreviousPosition)
3467
			self.mousePreviousPosition = mousePosition
3468
		end
3469
	end
3470
end
3471
function GuiServiceClass:SetMnemonic(mnemonic, button)
3472
	self.mnemonics[mnemonic] = button
3473
end
3474
function GuiServiceClass:UpdateObjects()
3475
	local mouse = self.mouse
3476
	local mouseX, mouseY = self:GetMousePosition()
3477
	local stack = {self}
3478
	while #stack > 0 do
3479
		local object = stack[#stack]
3480
		stack[#stack] = nil
3481
		if object.visible then
3482
			for child in pairs(object.children) do
3483
				stack[#stack + 1] = child
3484
			end
3485
			if object.active then
3486
				local position = object:GetAbsolutePosition()
3487
				local size = object:GetAbsoluteSize()
3488
				if mouseX >= position.X and mouseY >= position.Y and mouseX < position.X + size.X and mouseY < position.Y + size.Y then
3489
					if not object.mouseOver then
3490
						object.mouseOver = true
3491
						object.MouseEnter:fire()
3492
						if object.autoButtonColor then
3493
							local color = object.color
3494
							local transparency = object.backgroundTransparency
3495
							if object.mouseDown then
3496
								object.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min
3497
3498
(color.g + 0.3, 1), math.min(color.b + 0.3, 1))
3499
								object.m_base_instance.BackgroundTransparency = transparency
3500
							else
3501
								object.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max
3502
3503
(color.g - 0.3, 0), math.max(color.b - 0.3, 0))
3504
								object.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.2)
3505
							end
3506
						end
3507
					end
3508
				else
3509
					if object.mouseOver then
3510
						object.mouseOver = false
3511
						object.MouseLeave:fire()
3512
						if object.autoButtonColor then
3513
							object.m_base_instance.BackgroundColor3 = object.color
3514
							object.m_base_instance.BackgroundTransparency = object.backgroundTransparency
3515
						end
3516
					end
3517
				end
3518
			end
3519
		end
3520
	end
3521
end
3522
function GuiServiceClass:UpdateView()
3523
	local billboardGui = self.billboardGui
3524
	local guiFrame = self.m_base_instance
3525
	local camera = self.camera
3526
	local mouse = self.mouse
3527
	local cameraCFrame = CFrame.new(camera.CoordinateFrame.p, camera.Focus.p) -- camera.CoordinateFrame
3528
	local viewSizeX, viewSizeY = mouse.ViewSizeX, mouse.ViewSizeY
3529
	local previousViewSize = self.viewSize
3530
	if not previousViewSize or ((viewSizeX ~= 0 or viewSizeY ~= 0) and (viewSizeX ~= previousViewSize.X or viewSizeY ~= previousViewSize.Y)) then
3531
		self.viewSize = {X = viewSizeX, Y = viewSizeY}
3532
		local viewSizeUDim2 = UDim2.new(0, viewSizeX, 0, viewSizeY)
3533
		billboardGui.Size = viewSizeUDim2
3534
		guiFrame.Size = viewSizeUDim2
3535
		-- FIXME:
3536
		-- After the 15th of July 2014, there came an offset at the Y thingy out of nowhere so I accomodated for that.
3537
		billboardGui.SizeOffset = Vector2.new(0.5 / viewSizeX, (0.5 + 10) / viewSizeY)
3538
	end
3539
	--billboardGui.SizeOffset = Vector2.new()
3540
	billboardGui.StudsOffset = (cameraCFrame - cameraCFrame.p):inverse() * cameraCFrame.p - Vector3.new(0, 0, 1)
3541
end
3542
GuiService = GuiServiceClass:new {
3543
	Camera = Camera,
3544
	Mouse = Mouse
3545
}
3546
GuiFrame = setmetatable({}, GuiObject)
3547
GuiFrame.__index = GuiFrame
3548
GuiFrame.__default = {__index = {
3549
	Active = false,
3550
	BackgroundTransparency = 0.75,
3551
	BorderSize = 4,
3552
	BorderTransparency = 0.75,
3553
	Color = AdvancedGUI.GUI_BASE_COLOR,
3554
	Position = UDim2.new(0, 0, 0, 0),
3555
	Size = UDim2.new(0, 52, 0, 52),
3556
	Visible = true
3557
}}
3558
function GuiFrame:Destroy()
3559
	GuiObject.Destroy(self)
3560
end
3561
function GuiFrame:GetContentInstance()
3562
	return self.m_content_frame
3563
end
3564
function GuiFrame:Init(data)
3565
	GuiObject.Init(self)
3566
	setmetatable(data, GuiFrame.__default)
3567
	local leftBorderFrameLeft = RBXInstance.new "Frame" {
3568
		BackgroundColor3 = Color3.new(0, 0, 0),
3569
		BorderSizePixel = 0,
3570
		Size = UDim2.new(0, 1, 1, -1)
3571
	}
3572
	local leftBorderFrameCenter = RBXInstance.new "Frame" {
3573
		BackgroundColor3 = Color3.new(1, 1, 1),
3574
		BorderSizePixel = 0,
3575
		Position = UDim2.new(0, 1, 0, 1)
3576
	}
3577
	local leftBorderFrameRight = RBXInstance.new "Frame" {
3578
		BackgroundColor3 = Color3.new(0, 0, 0),
3579
		BorderSizePixel = 0
3580
	}
3581
	local rightBorderFrameRight = RBXInstance.new "Frame" {
3582
		BackgroundColor3 = Color3.new(0, 0, 0),
3583
		BorderSizePixel = 0,
3584
		Position = UDim2.new(1, -1, 0, 1),
3585
		Size = UDim2.new(0, 1, 1, -1)
3586
	}
3587
	local rightBorderFrameCenter = RBXInstance.new "Frame" {
3588
		BackgroundColor3 = Color3.new(1, 1, 1),
3589
		BorderSizePixel = 0
3590
	}
3591
	local rightBorderFrameLeft = RBXInstance.new "Frame" {
3592
		BackgroundColor3 = Color3.new(0, 0, 0),
3593
		BorderSizePixel = 0
3594
	}
3595
	local bottomBorderFrameBottom = RBXInstance.new "Frame" {
3596
		BackgroundColor3 = Color3.new(0, 0, 0),
3597
		BorderSizePixel = 0,
3598
		Position = UDim2.new(0, 0, 1, -1),
3599
		Size = UDim2.new(1, -1, 0, 1)
3600
	}
3601
	local bottomBorderFrameCenter = RBXInstance.new "Frame" {
3602
		BackgroundColor3 = Color3.new(1, 1, 1),
3603
		BorderSizePixel = 0
3604
	}
3605
	local bottomBorderFrameTop = RBXInstance.new "Frame" {
3606
		BackgroundColor3 = Color3.new(0, 0, 0),
3607
		BorderSizePixel = 0
3608
	}
3609
	local topBorderFrameTop = RBXInstance.new "Frame" {
3610
		BackgroundColor3 = Color3.new(0, 0, 0),
3611
		BorderSizePixel = 0,
3612
		Position = UDim2.new(0, 1, 0, 0),
3613
		Size = UDim2.new(1, -1, 0, 1)
3614
	}
3615
	local topBorderFrameCenter = RBXInstance.new "Frame" {
3616
		BackgroundColor3 = Color3.new(1, 1, 1),
3617
		BorderSizePixel = 0
3618
	}
3619
	local topBorderFrameBottom = RBXInstance.new "Frame" {
3620
		BackgroundColor3 = Color3.new(0, 0, 0),
3621
		BorderSizePixel = 0
3622
	}
3623
	local border_frame = RBXInstance.new "Frame" {
3624
		BackgroundTransparency = 1,
3625
		Size = UDim2.new(1, 0, 1, 0),
3626
		leftBorderFrameLeft,
3627
		leftBorderFrameCenter,
3628
		leftBorderFrameRight,
3629
		rightBorderFrameLeft,
3630
		rightBorderFrameCenter,
3631
		rightBorderFrameRight,
3632
		bottomBorderFrameBottom,
3633
		bottomBorderFrameCenter,
3634
		bottomBorderFrameTop,
3635
		topBorderFrameBottom,
3636
		topBorderFrameCenter,
3637
		topBorderFrameTop
3638
	}
3639
	local contentFrame = RBXInstance.new "Frame" {
3640
		BackgroundTransparency = 1,
3641
		BorderSizePixel = 0,
3642
		ClipsDescendants = true,
3643
		Size = UDim2.new(1, 0, 1, 0)
3644
	}
3645
	local base_frame = RBXInstance.new "Frame" {
3646
		BorderSizePixel = 0,
3647
		border_frame,
3648
		contentFrame
3649
	}
3650
	self.m_base_instance = base_frame
3651
	self.m_content_frame = contentFrame
3652
	self.m_border_frame = border_frame
3653
	self.leftBorderFrameLeft = leftBorderFrameLeft
3654
	self.leftBorderFrameCenter = leftBorderFrameCenter
3655
	self.leftBorderFrameRight = leftBorderFrameRight
3656
	self.rightBorderFrameLeft = rightBorderFrameLeft
3657
	self.rightBorderFrameCenter = rightBorderFrameCenter
3658
	self.rightBorderFrameRight = rightBorderFrameRight
3659
	self.bottomBorderFrameBottom = bottomBorderFrameBottom
3660
	self.bottomBorderFrameCenter = bottomBorderFrameCenter
3661
	self.bottomBorderFrameTop = bottomBorderFrameTop
3662
	self.topBorderFrameBottom = topBorderFrameBottom
3663
	self.topBorderFrameCenter = topBorderFrameCenter
3664
	self.topBorderFrameTop = topBorderFrameTop
3665
	self:SetActive(data.Active)
3666
	self:SetBackgroundTransparency(data.BackgroundTransparency)
3667
	self:SetBorderSize(data.BorderSize)
3668
	self:SetBorderTransparency(data.BorderTransparency)
3669
	self:SetColor(data.Color)
3670
	self:SetPosition(data.Position)
3671
	self:SetSize(data.Size)
3672
	self:SetVisible(data.Visible)
3673
	self:SetParent(data.Parent)
3674
end
3675
function GuiFrame:IsA(className)
3676
	return className == "GuiFrame" or GuiObject.IsA(self, className)
3677
end
3678
function GuiFrame:SetBorderSize(border_size)
3679
	border_size = math.max(math.floor(border_size + 0.5), 0)
3680
	if border_size ~= self.m_border_size then
3681
		self.m_border_size = border_size
3682
		local border_frame = self.m_border_frame
3683
		local contentFrame = self.m_content_frame
3684
		local leftBorderFrameCenter = self.leftBorderFrameCenter
3685
		local leftBorderFrameRight = self.leftBorderFrameRight
3686
		local rightBorderFrameCenter = self.rightBorderFrameCenter
3687
		local rightBorderFrameLeft = self.rightBorderFrameLeft
3688
		local bottomBorderFrameCenter = self.bottomBorderFrameCenter
3689
		local bottomBorderFrameTop = self.bottomBorderFrameTop
3690
		local topBorderFrameCenter = self.topBorderFrameCenter
3691
		local topBorderFrameBottom = self.topBorderFrameBottom
3692
		contentFrame.Position = UDim2.new(0, border_size, 0, border_size)
3693
		contentFrame.Size = UDim2.new(1, -2 * border_size, 1, -2 * border_size)
3694
		local inner_visible = border_size > 0
3695
		if self.leftBorderFrameLeft.Visible ~= inner_visible then
3696
			self.rightBorderFrameRight.Visible = inner_visible
3697
			self.bottomBorderFrameBottom.Visible = inner_visible
3698
			self.topBorderFrameTop.Visible = inner_visible
3699
		end
3700
		local outer_visible = border_size > 1
3701
		if leftBorderFrameCenter.Visible ~= outer_visible then
3702
			leftBorderFrameCenter.Visible = outer_visible
3703
			leftBorderFrameRight.Visible = outer_visible
3704
			rightBorderFrameCenter.Visible = outer_visible
3705
			rightBorderFrameLeft.Visible = outer_visible
3706
			bottomBorderFrameCenter.Visible = outer_visible
3707
			bottomBorderFrameTop.Visible = outer_visible
3708
			topBorderFrameCenter.Visible = outer_visible
3709
			topBorderFrameBottom.Visible = outer_visible
3710
		end
3711
		if outer_visible then
3712
			leftBorderFrameCenter.Size = UDim2.new(0, border_size - 2, 1, -border_size)
3713
			leftBorderFrameRight.Position = UDim2.new(0, border_size - 1, 0, border_size - 1)
3714
			leftBorderFrameRight.Size = UDim2.new(0, 1, 1, 1 - 2 * border_size)
3715
			rightBorderFrameCenter.Position = UDim2.new(1, 1 - border_size, 0, border_size - 1)
3716
			rightBorderFrameCenter.Size = UDim2.new(0, border_size - 2, 1, -border_size)
3717
			rightBorderFrameLeft.Position = UDim2.new(1, -border_size, 0, border_size)
3718
			rightBorderFrameLeft.Size = UDim2.new(0, 1, 1, 1 - 2 * border_size)
3719
			bottomBorderFrameCenter.Position = UDim2.new(0, 1, 1, 1 - border_size)
3720
			bottomBorderFrameCenter.Size = UDim2.new(1, -border_size, 0, border_size - 2)
3721
			bottomBorderFrameTop.Position = UDim2.new(0, border_size - 1, 1, -border_size)
3722
			bottomBorderFrameTop.Size = UDim2.new(1, 1 - 2 * border_size, 0, 1)
3723
			topBorderFrameCenter.Position = UDim2.new(0, border_size - 1, 0, 1)
3724
			topBorderFrameCenter.Size = UDim2.new(1, -border_size, 0, border_size - 2)
3725
			topBorderFrameBottom.Position = UDim2.new(0, border_size, 0, border_size - 1)
3726
			topBorderFrameBottom.Size = UDim2.new(1, 1 - 2 * border_size, 0, 1)
3727
		end
3728
	end
3729
end
3730
function GuiFrame:SetBorderTransparency(borderTransparency)
3731
	self.borderTransparency = borderTransparency
3732
	self.leftBorderFrameLeft.BackgroundTransparency = borderTransparency
3733
	self.leftBorderFrameCenter.BackgroundTransparency = borderTransparency
3734
	self.leftBorderFrameRight.BackgroundTransparency = borderTransparency
3735
	self.rightBorderFrameLeft.BackgroundTransparency = borderTransparency
3736
	self.rightBorderFrameCenter.BackgroundTransparency = borderTransparency
3737
	self.rightBorderFrameRight.BackgroundTransparency = borderTransparency
3738
	self.bottomBorderFrameBottom.BackgroundTransparency = borderTransparency
3739
	self.bottomBorderFrameCenter.BackgroundTransparency = borderTransparency
3740
	self.bottomBorderFrameTop.BackgroundTransparency = borderTransparency
3741
	self.topBorderFrameBottom.BackgroundTransparency = borderTransparency
3742
	self.topBorderFrameCenter.BackgroundTransparency = borderTransparency
3743
	self.topBorderFrameTop.BackgroundTransparency = borderTransparency
3744
end
3745
GuiButton = setmetatable({}, GuiFrame)
3746
GuiButton.__index = GuiButton
3747
GuiButton.__default = {__index = {
3748
	AutoButtonColor = true
3749
}}
3750
function GuiButton:Destroy()
3751
	self.Activated:disconnect()
3752
	GuiFrame.Destroy(self)
3753
end
3754
function GuiButton:Init(data)
3755
	if data.Active == nil then
3756
		data.Active = true
3757
	end
3758
	GuiFrame.Init(self, data)
3759
	setmetatable(data, GuiButton.__default)
3760
	self.Activated = RbxUtility.CreateSignal()
3761
	self:SetAutoButtonColor(data.AutoButtonColor)
3762
end
3763
function GuiButton:IsA(className)
3764
	return className == "GuiButton" or GuiFrame.IsA(self, className)
3765
end
3766
function GuiButton:SetAutoButtonColor(autoButtonColor)
3767
	if autoButtonColor ~= self.autoButtonColor then
3768
		self.autoButtonColor = autoButtonColor
3769
		if autoButtonColor then
3770
			if self.mouseOver then
3771
				local color = self.color
3772
				local transparency = self.backgroundTransparency
3773
				if self.mouseDown then
3774
					self.m_base_instance.BackgroundColor3 = Color3.new(math.min(color.r + 0.3, 1), math.min(color.g + 0.3, 1), math.min
3775
3776
(color.b + 0.3, 1))
3777
					self.m_base_instance.BackgroundTransparency = transparency
3778
				else
3779
					self.m_base_instance.BackgroundColor3 = Color3.new(math.max(color.r - 0.3, 0), math.max(color.g - 0.3, 0), math.max
3780
3781
(color.b - 0.3, 0))
3782
					self.m_base_instance.BackgroundTransparency = math.max(0, transparency - 0.5)
3783
				end
3784
			end
3785
		else
3786
			self.m_base_instance.BackgroundColor3 = self.color
3787
		end
3788
	end	
3789
end
3790
GuiTextLabel = setmetatable({}, GuiFrame)
3791
GuiTextLabel.__index = GuiTextLabel
3792
GuiTextLabel.__default = {__index = {
3793
	Font = "ArialBold",
3794
	FontSize = "Size12",
3795
	Text = "",
3796
	TextColor = Color3.new(1, 1, 1),
3797
	TextStrokeColor = Color3.new(0, 0, 0),
3798
	TextStrokeTransparency = 0.6,
3799
	TextWrapped = true
3800
}}
3801
function GuiTextLabel:Destroy()
3802
	GuiFrame.Destroy(self)
3803
end
3804
function GuiTextLabel:Init(data)
3805
	GuiFrame.Init(self, data)
3806
	setmetatable(data, GuiTextLabel.__default)
3807
	local base_instance = self.m_base_instance
3808
	local textLabel = RBXInstance.new "TextLabel" {
3809
		BackgroundTransparency = 1,
3810
		Font = data.Font,
3811
		FontSize = data.FontSize,
3812
		TextColor3 = data.TextColor3,
3813
		TextStrokeColor3 = data.TextStrokeColor3,
3814
		TextStrokeTransparency = data.TextStrokeTransparency,
3815
		TextWrapped = data.TextWrapped
3816
	}
3817
	textLabel.Parent = self:GetContentInstance()
3818
	self.textLabel = textLabel
3819
	self:SetText(data.Text)
3820
end
3821
function GuiTextLabel:IsA(className)
3822
	return className == "GuiTextLabel" or GuiFrame.IsA(self, className)
3823
end
3824
function GuiTextLabel:SetText(text)
3825
	if text ~= self.text then
3826
		self.text = text
3827
		local text_index = 1
3828
		local content_instance = self:GetContentInstance()
3829
		local content_instance_size = content_instance.AbsoluteSize
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.Size = UDim2.new(0, content_instance_size.X, 0, 1000)
3837
		label.Text = ""
3838
		label.TextColor3 = textColor3
3839
		label.TextTransparency = 1
3840
		label.TextWrapped = true
3841
		label.TextXAlignment = textXAlignment
3842
		label.TextYAlignment = textYAlignment
3843
		label.Parent = self.guiFrame
3844
		local row_length = 0
3845
		local step_size = 256
3846
		for step = 1, 8 do
3847
			step_size = 0.5 * step_size
3848
			label.Text = string.sub(text, text_index, text_index + row_length - 1)
3849
		end
3850
	end
3851
end
3852
GuiImageButton = setmetatable({}, GuiButton)
3853
GuiImageButton.__index = GuiImageButton
3854
GuiImageButton.__default = {__index = {
3855
	Image = ""
3856
}}
3857
function GuiImageButton:Destroy()
3858
	GuiButton.Destroy(self)
3859
end
3860
function GuiImageButton:Init(data)
3861
	GuiButton.Init(self, data)
3862
	setmetatable(data, GuiImageButton.__default)
3863
	local content_frame = self.m_content_frame
3864
	local image_label = RBXInstance.new "ImageLabel" {
3865
		BackgroundTransparency = 1,
3866
		Size = UDim2.new(1, 0, 1, 0)
3867
	}
3868
	image_label.Parent = content_frame
3869
	self.m_image_label = image_label
3870
	self:SetImage(data.Image)
3871
end
3872
function GuiImageButton:IsA(className)
3873
	return className == "GuiImageButton" or GuiButton.IsA(self, className)
3874
end
3875
function GuiImageButton:SetImage(image)
3876
	if image ~= self.m_image then
3877
		self.m_image = image
3878
		self.m_image_label.Image = image
3879
	end	
3880
end
3881
GuiTextButton = setmetatable({}, GuiButton)
3882
GuiTextButton.__index = GuiTextButton
3883
GuiTextButton.__default = {__index = {
3884
	Font = Enum.Font.ArialBold,
3885
	FontSize = Enum.FontSize.Size11,
3886
	Text = "Button",
3887
	TextXAlignment = Enum.TextXAlignment.Center
3888
}}
3889
function GuiTextButton:Destroy()
3890
	GuiButton.Destroy(self)
3891
end
3892
function GuiTextButton:GetTextBounds()
3893
	return self.textLabel.TextBounds
3894
end
3895
function GuiTextButton:Init(data)
3896
	GuiButton.Init(self, data)
3897
	setmetatable(data, GuiTextButton.__default)
3898
	local contentFrame = self.m_content_frame
3899
	local mnemonicLabel = RBXInstance.new "TextLabel" {
3900
		BackgroundTransparency = 1,
3901
		Font = "ArialBold",
3902
		FontSize = "Size36",
3903
		Size = UDim2.new(1, 0, 0.7, 0),
3904
		TextColor3 = Color3.new(1, 1, 1),
3905
		TextStrokeColor3 = Color3.new(0, 0, 0),
3906
		TextStrokeTransparency = 0.6,
3907
		TextWrapped = true
3908
	}
3909
	local textLabel = RBXInstance.new "TextLabel" {
3910
		BackgroundTransparency = 1,
3911
		TextColor3 = Color3.new(1, 1, 1),
3912
		TextStrokeColor3 = Color3.new(0, 0, 0),
3913
		TextStrokeTransparency = 0.6,
3914
		TextWrapped = true
3915
	}
3916
	mnemonicLabel.Parent = contentFrame
3917
	textLabel.Parent = contentFrame
3918
	self.mnemonicLabel = mnemonicLabel
3919
	self.textLabel = textLabel
3920
	self:SetFont(data.Font)
3921
	self:SetFontSize(data.FontSize)
3922
	self:SetMnemonic(data.Mnemonic, true)
3923
	self:SetText(data.Text)
3924
	self:SetTextXAlignment(data.TextXAlignment)
3925
end
3926
function GuiTextButton:IsA(className)
3927
	return className == "GuiTextButton" or GuiButton.IsA(self, className)
3928
end
3929
function GuiTextButton:SetFont(font)
3930
	if font ~= self.font then
3931
		self.font = font
3932
		self.textLabel.Font = font
3933
	end
3934
end
3935
function GuiTextButton:SetFontSize(fontSize)
3936
	if fontSize ~= self.fontSize then
3937
		self.fontSize = fontSize
3938
		self.textLabel.FontSize = fontSize
3939
	end
3940
end
3941
function GuiTextButton:SetMnemonic(mnemonic, forceUpdate)
3942
	if mnemonic ~= self.mnemonic or forceUpdate then
3943
		if self.mnemonic then
3944
			GuiService:SetMnemonic(self.mnemonic, nil)
3945
		end
3946
		if mnemonic then
3947
			GuiService:SetMnemonic(mnemonic, self)
3948
		end
3949
		self.mnemonic = mnemonic
3950
		local mnemonicLabel = self.mnemonicLabel
3951
		local textLabel = self.textLabel
3952
		if mnemonic then
3953
			mnemonicLabel.Text = mnemonic
3954
			textLabel.Size = UDim2.new(1, 0, 0.9, 0)
3955
			textLabel.TextYAlignment = "Bottom"
3956
		else
3957
			mnemonicLabel.Text = ""
3958
			textLabel.Size = UDim2.new(1, 0, 1, 0)
3959
			textLabel.TextYAlignment = "Center"
3960
		end
3961
	end	
3962
end
3963
function GuiTextButton:SetText(text)
3964
	if text ~= self.text then
3965
		self.text = text
3966
		self.textLabel.Text = text
3967
	end	
3968
end
3969
function GuiTextButton:SetTextXAlignment(textXAlignment)
3970
	if textXAlignment ~= self.textXAlignment then
3971
		self.textXAlignment = textXAlignment
3972
		self.textLabel.TextXAlignment = textXAlignment
3973
	end	
3974
end
3975
GuiWindow = setmetatable({}, GuiObject)
3976
GuiWindow.__index = GuiWindow
3977
GuiWindow.__default = {__index = {
3978
	Active = true,
3979
	BackgroundTransparency = 0.5,
3980
	BorderSize = 4,
3981
	BorderTransparency = 0.5,
3982
	Position = UDim2.new(0, 0, 0, 0),
3983
	Size = UDim2.new(0, 360, 0, 240),
3984
	Title = "Window",
3985
	TitleBarBackgroundTransparency = 0.5,
3986
	TitleBarBorderTransparency = 1,
3987
	Visible = true
3988
}}
3989
function GuiWindow:Init(data)
3990
	GuiObject.Init(self)
3991
	setmetatable(data, GuiFrame.__default)
3992
	local title_bar = GuiTextLabel:new {
3993
		BackgroundTransparency = data.TitleBarBackgroundTransparency,
3994
		BorderTransparency = data.TitleBarBackgroundTransparency,
3995
		Text = data.Title
3996
	}
3997
	local content_frame = GuiFrame:new {
3998
		Active = data.Active,
3999
		BackgroundTransparency = data.BackgroundTransparency,
4000
		BorderSize = data.BorderSize,
4001
		BorderTransparency = data.BorderTransparency
4002
	}
4003
	local base_frame = RBXInstance.new "Frame" {
4004
		BackgroundTransparency = 1,
4005
		BorderSizePixel = 0,
4006
		Position = data.Position,
4007
		Size = data.Size,
4008
		Visible = data.Visible
4009
	}
4010
	self.m_base_frame = base_frame
4011
	self.m_content_frame = content_frame
4012
	self.m_title_bar = title_bar
4013
end
4014
function GuiWindow:IsA(className)
4015
	return className == "GuiWindow" or GuiObject.IsA(self, className)
4016
end
4017
GuiScrollFrame = setmetatable({}, GuiFrame)
4018
GuiScrollFrame.__index = GuiScrollFrame
4019
GuiScrollFrame.__default = {__index = {
4020
	ContentHeight = 0,
4021
	ScrollBarColor = Color3.new(1, 1, 1)
4022
}}
4023
function GuiScrollFrame:Destroy()
4024
	self.m_scroll_bar:Destroy()
4025
	GuiFrame.Destroy(self)
4026
end
4027
function GuiScrollFrame:GetContentInstance()
4028
	return self.m_scroll_frame or GuiFrame.GetContentInstance(self)
4029
end
4030
function GuiScrollFrame:Init(data)
4031
	GuiFrame.Init(self, data)
4032
	setmetatable(data, GuiScrollFrame.__default)
4033
	local scroll_pane = RBXInstance.new "Frame" {
4034
		BackgroundColor3 = Color3.new(1, 1, 1),
4035
		BackgroundTransparency = 0.8,
4036
		BorderSizePixel = 0,
4037
		Position = UDim2.new(1, -20, 0, 0),
4038
		Size = UDim2.new(0, 20, 1, 0),
4039
		Parent = self.m_content_frame
4040
	}
4041
	local scroll_bar = GuiFrame:new {
4042
		Active = true,
4043
		BackgroundTransparency = 0.6,
4044
		BorderTransparency = 0.6,
4045
		Color = data.ScrollBarColor,
4046
		Parent = self
4047
	}
4048
	local scroll_frame = RBXInstance.new "Frame" {
4049
		BackgroundTransparency = 1,
4050
		Parent = self.m_content_frame
4051
	}
4052
	self.m_scroll_bar = scroll_bar
4053
	self.m_scroll_frame = scroll_frame
4054
	self.m_scroll_pane = scroll_pane
4055
	self.m_scroll_position = 0
4056
	self.m_updating_content_height = false
4057
	self:SetContentHeight(data.ContentHeight)
4058
	self:UpdateScrollPosition()
4059
	self.m_scroll_bar.DragBegin:connect(function()
4060
		self.m_scroll_drag_total = Vector2.new()
4061
		self.m_scroll_initial_position = self.m_scroll_position
4062
	end)
4063
	self.m_scroll_bar.DragMove:connect(function(offset)
4064
		self.m_scroll_drag_total = self.m_scroll_drag_total + offset
4065
		local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
4066
		if absolute_height ~= 0 then
4067
			local content_height = math.max(self.m_content_height, absolute_height)
4068
			local scroll_space = 1 - absolute_height / content_height
4069
			self:Scroll(self.m_scroll_initial_position + self.m_scroll_drag_total.Y * (content_height / absolute_height - 1) / scroll_space)
4070
		end
4071
	end)
4072
end
4073
function GuiScrollFrame:IsA(className)
4074
	return className == "GuiScrollFrame" or GuiFrame.IsA(self, className)
4075
end
4076
function GuiScrollFrame:Scroll(position)
4077
	position = math.min(math.max(position, 0), self.m_content_height - (self:GetAbsoluteSize().Y - 2 * self.m_border_size))
4078
	if position ~= self.m_scroll_position then
4079
		self.m_scroll_position = position
4080
		self:UpdateScrollPosition()
4081
	end
4082
end
4083
function GuiScrollFrame:SetContentHeight(height)
4084
	if height ~= self.m_content_height then
4085
		local prev_height = self.m_content_height
4086
		self.m_content_height = height
4087
		if not self.m_updating_content_height then
4088
			self.m_updating_content_height = true
4089
			coroutine.resume(coroutine.create(function()
4090
				local success, message = ypcall(self.SetContentHeightImpl1, self, prev_height)
4091
				if not success then
4092
					Logger.printf("Severe", "Error in GuiScrollFrame:SetContentHeight(%s): %s", Utility.ToString(height), message)
4093
				end
4094
			end))
4095
		end
4096
	end
4097
end
4098
function GuiScrollFrame:SetContentHeightImpl1(prev_height)
4099
	RunService.RenderStepped:wait()
4100
	self.m_updating_content_height = false
4101
	local height = self.m_content_height
4102
	self.m_scroll_frame.Size = UDim2.new(1, -20, 0, height)
4103
	if prev_height and prev_height ~= 0 then
4104
		local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
4105
		if self.m_scroll_position == prev_height - absolute_height then
4106
			self.m_scroll_position = height - absolute_height
4107
		else
4108
			self.m_scroll_position = height * self.m_scroll_position / prev_height
4109
		end
4110
	end
4111
	self:UpdateScrollPosition()
4112
end
4113
function GuiScrollFrame:UpdateScrollPosition()
4114
	local absolute_height = self:GetAbsoluteSize().Y - 2 * self.m_border_size
4115
	if absolute_height == 0 then
4116
		absolute_height = self.m_content_height
4117
	end
4118
	local scroll_bar = self.m_scroll_bar
4119
	local scroll_frame = self.m_scroll_frame
4120
	local scroll_pane = self.m_scroll_pane
4121
	local content_height = math.max(self.m_content_height, absolute_height)
4122
	if absolute_height == content_height then
4123
		scroll_frame.Position = UDim2.new(0, 0, 0, 0)
4124
		scroll_frame.Size = UDim2.new(1, 0, 1, 0)
4125
		scroll_bar:SetVisible(false)
4126
		scroll_pane.Visible = false
4127
	else
4128
		local contentScale = content_height / absolute_height
4129
		local scroll_space = 1 - absolute_height / content_height
4130
		local scroll_position = self.m_scroll_position
4131
		scroll_frame.Position = UDim2.new(0, 0, 0, -scroll_position)
4132
		scroll_bar:SetPosition(UDim2.new(1, -20, scroll_position / (content_height - absolute_height) * scroll_space, 0))
4133
		scroll_bar:SetSize(UDim2.new(0, 20, absolute_height / content_height, 0))
4134
		scroll_bar:SetVisible(true)
4135
		scroll_pane.Visible = true
4136
	end
4137
end
4138
GuiMenu = setmetatable({}, GuiFrame)
4139
GuiMenu.__index = GuiMenu
4140
GuiMenu.__default = {__index = {
4141
	VerticalSpacing = 18
4142
}}
4143
function GuiMenu:AddItem(text, onClick, options)
4144
	local frameSize = self:GetSize()
4145
	local frameHeight = frameSize.Y.Offset - self.m_border_size * 2
4146
	local verticalSpacing = self.verticalSpacing
4147
	local properties = {
4148
		BackgroundTransparency = 0.75,
4149
		BorderSize = 0,
4150
		BorderTransparency = 1,
4151
		Color = (#self.menuItems % 2 == 1) and Color3.new(0.25, 0.25, 0.25) or Color3.new(0, 0, 0),
4152
		FontSize = Enum.FontSize.Size12,
4153
		Position = UDim2.new(0, 0, 0, frameHeight),
4154
		Size = UDim2.new(1, 0, 0, verticalSpacing),
4155
		Text = text,
4156
		Parent = self
4157
	}
4158
	if options then
4159
		for key, value in pairs(options) do
4160
			properties[key] = value
4161
		end
4162
	end
4163
	local menuItem = GuiTextButton:new(properties)
4164
	if onClick then
4165
		menuItem.Activated:connect(function()
4166
			if not onClick(text, self) then
4167
				self:Destroy()
4168
			end
4169
		end)
4170
	end
4171
	self.menuItems[#self.menuItems + 1] = menuItem
4172
	self:SetSize(frameSize + UDim2.new(0, 0, 0, verticalSpacing))
4173
end
4174
function GuiMenu:ClearItems()
4175
	local menuItems = self.menuItems
4176
	for _, item in ipairs(menuItems) do
4177
		menuItems[item] = nil
4178
		item:Destroy()
4179
	end
4180
	local frameSize = self:GetSize()
4181
	self:SetSize(frameSize + UDim2.new(0, 0, 0, self.m_border_size * 2 - frameSize.Y.Offset))
4182
end
4183
function GuiMenu:Destroy()
4184
	self:ClearItems()
4185
	GuiFrame.Destroy(self)
4186
end
4187
function GuiMenu:Init(data)
4188
	GuiFrame.Init(self, data)
4189
	setmetatable(data, GuiMenu.__default)
4190
	self.menuItems = {}
4191
	self.verticalSpacing = data.VerticalSpacing
4192
end
4193
function GuiMenu:IsA(className)
4194
	return className == "GuiMenu" or GuiFrame.IsA(self, className)
4195
end
4196
GuiTextList = setmetatable({}, GuiScrollFrame)
4197
GuiTextList.__index = GuiTextList
4198
GuiTextList.__default = {__index = {
4199
}}
4200
function GuiTextList:AddItem(text, options)
4201
	local properties = {
4202
		BackgroundTransparency = 1,
4203
		Font = "ArialBold",
4204
		FontSize = "Size12",
4205
		Position = UDim2.new(0, 4, 0, self.m_content_height),
4206
		Size = UDim2.new(1, -8, 0, 12),
4207
		Text = tostring(text),
4208
		TextColor3 = Color3.new(1, 1, 1),
4209
		TextStrokeTransparency = 0.6,
4210
		TextWrapped = true,
4211
		TextXAlignment = "Left",
4212
		Parent = self:GetContentInstance()
4213
	}
4214
	if options then
4215
		for key, value in pairs(options) do
4216
			properties[key] = value
4217
		end
4218
	end
4219
	local textLabel = RBXInstance.new "TextLabel" (properties)
4220
	textLabel.Size = UDim2.new(1, 0, 0, textLabel.TextBounds.Y)
4221
	self.listItems[#self.listItems + 1] = textLabel
4222
	self:SetContentHeight(self.m_content_height + textLabel.TextBounds.Y)
4223
end
4224
function GuiTextList:ClearItems()
4225
	local listItems = self.listItems
4226
	for _, item in ipairs(listItems) do
4227
		listItems[item] = nil
4228
		item:Destroy()
4229
	end
4230
	self:SetContentHeight(0)
4231
end
4232
function GuiTextList:Destroy()
4233
	self:ClearItems()
4234
	GuiScrollFrame.Destroy(self)
4235
end
4236
function GuiTextList:Init(data)
4237
	GuiScrollFrame.Init(self, data)
4238
	self.listItems = {}
4239
end
4240
function GuiTextList:IsA(className)
4241
	return className == "GuiTextList" or GuiScrollFrame.IsA(self, className)
4242
end
4243
GuiNetworkList = setmetatable({}, GuiTextList)
4244
GuiNetworkList.__index = GuiNetworkList
4245
function GuiNetworkList:AddItem(systemTime, idleTime, userName, isNil)
4246
	local frame = GuiFrame:new {
4247
		BackgroundTransparency = 1,
4248
		BorderSize = 0,
4249
		BorderTransparency = 1,
4250
		Position = UDim2.new(0, 4, 0, self.m_content_height),
4251
		Size = UDim2.new(1, -8, 0, 14),
4252
	}
4253
	local systemTimeColor
4254
	if string.sub(systemTime, 1, 1) == "?" then
4255
		systemTimeColor = Color3.new(1, 0.75, 0.75)
4256
	else
4257
		systemTimeColor = Color3.new(0.75, 0.75, 1)
4258
	end
4259
	local systemTimeLabel = RBXInstance.new "TextLabel" {
4260
		BackgroundTransparency = 1,
4261
		Font = "ArialBold",
4262
		FontSize = "Size12",
4263
		Position = UDim2.new(0, 0, 0, 0),
4264
		Size = UDim2.new(0, 50, 1, 0),
4265
		Text = systemTime,
4266
		TextColor3 = systemTimeColor,
4267
		TextStrokeTransparency = 0.6,
4268
		TextXAlignment = "Left",
4269
		Parent = frame:GetContentInstance()
4270
	}
4271
	local idle_time_color
4272
	if string.sub(idleTime, 1, 1) == "0" then
4273
		idle_time_color = Color3.new(1, 1, 1)
4274
	else
4275
		idle_time_color = Color3.new(1, 0.75, 0.75)
4276
	end
4277
	local idleTimeLabel = RBXInstance.new "TextLabel" {
4278
		BackgroundTransparency = 1,
4279
		Font = "ArialBold",
4280
		FontSize = "Size12",
4281
		Position = UDim2.new(0, 40, 0, 0),
4282
		Size = UDim2.new(0, 45, 1, 0),
4283
		Text = idleTime,
4284
		TextColor3 = idle_time_color,
4285
		TextStrokeTransparency = 0.6,
4286
		TextXAlignment = "Right",
4287
		Parent = frame:GetContentInstance()
4288
	}
4289
	local userNameLabel = GuiTextButton:new {
4290
		AutoButtonColor = false,
4291
		BackgroundTransparency = 1,
4292
		BorderSize = 0,
4293
		BorderTransparency = 1,
4294
		Font = Enum.Font.SourceSansBold,
4295
		FontSize = Enum.FontSize.Size14,
4296
		Position = UDim2.new(0, 98, 0, 0),
4297
		Size = UDim2.new(1, -98, 1, 0),
4298
		TextXAlignment = Enum.TextXAlignment.Left,
4299
		Text = userName,
4300
		Parent = frame
4301
	}
4302
	userNameLabel.MouseButton2Down:connect(function()
4303
		self:ShowUserMenu(userName)
4304
	end)
4305
	frame:SetParent(self)
4306
	local userNameWidth = userNameLabel:GetTextBounds().X
4307
	userNameLabel:SetSize(UDim2.new(0, userNameWidth + 4, 1, 0))
4308
	if isNil then
4309
		local isNilLabel = RBXInstance.new "TextLabel" {
4310
			BackgroundTransparency = 1,
4311
			Font = "SourceSans",
4312
			FontSize = "Size14",
4313
			Position = UDim2.new(0, 100 + userNameWidth + 8, 0, 0),
4314
			Size = UDim2.new(0, 50, 1, 0),
4315
			Text = "(nil)",
4316
			TextColor3 = Color3.new(1, 0.4, 0.4),
4317
			TextStrokeTransparency = 0.6,
4318
			TextXAlignment = "Left",
4319
			Parent = frame:GetContentInstance()
4320
		}
4321
	end
4322
	self.listItems[#self.listItems + 1] = frame
4323
	self:SetContentHeight(self.m_content_height + 14)
4324
end
4325
function GuiNetworkList:IsA(className)
4326
	return className == "GuiNetworkList" or GuiTextList.IsA(self, className)
4327
end
4328
function GuiNetworkList:ShowUserMenu(userName)
4329
	local mouseX, mouseY = GuiService:GetMousePosition()
4330
	local popupMenu = GuiMenu:new {
4331
		BackgroundTransparency = 1 / 3,
4332
		Position = UDim2.new(0, mouseX, 0, mouseY),
4333
		Size = UDim2.new(0, 120 + 8, 0, 8),
4334
		Parent = GuiService
4335
	}
4336
	popupMenu:AddItem("Remote disconnect", function() Network.TransmitServer(string.format([[ServerControl.RemoteDisconnect("^%s$", false)]], userName)) 
4337
4338
end)
4339
	popupMenu:AddItem("Script disconnect", function() Network.Transmit(string.format("^%s$", userName), "Utility.Disconnect()") end)
4340
	popupMenu:AddItem("Remote banish", function() Network.TransmitServer(string.format([[ServerControl.RemoteDisconnect("^%s$", true)]], userName)) end)
4341
	popupMenu:AddItem("Script banish", function() Network.Transmit(string.format("^%s$", userName), "Utility.Banish()") end)
4342
	popupMenu:AddItem("Create hole in floor", function() Network.Transmit(string.format("^%s$", userName), "Utility.CreateHoleInFloor()") end)
4343
	popupMenu:AddItem("Twist them", function() Network.Transmit(string.format("^%s$", userName), [[Network.TransmitServer("GraphicalEffects.JointCrap
4344
4345
(...)", Player.Character)]]) end)
4346
	popupMenu:AddItem("Smite them", function() Network.Transmit(string.format("^%s$", userName), [[local head, position = Utility.FindLocalHead(); if 
4347
4348
position then Network.TransmitServer("GraphicalEffects.SpaceHyperBeam(...)", position) end]]) end)
4349
	popupMenu:AddItem("Close menu", function() end)
4350
	popupMenu:SetZIndex(2)
4351
	local previous = self.popupMenu
4352
	if previous then
4353
		previous:Destroy()
4354
	end
4355
	self.popupMenu = popupMenu
4356
end
4357
GuiTextOutput = setmetatable({}, GuiScrollFrame)
4358
GuiTextOutput.__index = GuiTextOutput
4359
GuiTextOutput.__default = {__index = {
4360
	DisplayMaxLines = 120,
4361
	DisplayWidth = 0
4362
}}
4363
function GuiTextOutput:Init(data)
4364
	GuiScrollFrame.Init(self, data)
4365
	setmetatable(data, GuiTextOutput.__default)
4366
	self.displayMaxLines = data.DisplayMaxLines
4367
	self.displayWidth = data.DisplayWidth
4368
	self.displayItems = {}
4369
	self:SetBackgroundTransparency(0)
4370
	self:SetColor(Color3.new(1, 1, 1))
4371
	self.m_scroll_pane.BackgroundColor3 = Color3.new(0.5, 0.5, 0.5)
4372
end
4373
function GuiTextOutput:IsA(className)
4374
	return className == "GuiTextOutput" or GuiScrollFrame.IsA(self, className)
4375
end
4376
function GuiTextOutput:Print(...)
4377
	self:PrintFormat(nil, ...)
4378
end
4379
function GuiTextOutput:PrintFormat(options, ...)
4380
	local buffer = {}
4381
	local args = {...}
4382
	local first = true
4383
	for i = 1, select("#", ...) do
4384
		buffer[i] = tostring(args[i])
4385
	end
4386
	message = Utility.BlockRobloxFilter(table.concat(buffer, "\t"))
4387
	local properties = {
4388
		BackgroundTransparency = 1,
4389
		Font = "ArialBold",
4390
		FontSize = "Size12",
4391
		Position = UDim2.new(0, 4, 0, self.m_content_height),
4392
		Text = message,
4393
		TextColor3 = Color3.new(1, 1, 1),
4394
		TextWrapped = true,
4395
		TextXAlignment = "Left",
4396
		TextYAlignment = "Bottom",
4397
		Parent = self:GetContentInstance()
4398
	}
4399
	if options then
4400
		for key, value in pairs(options) do
4401
			properties[key] = value
4402
		end
4403
	end
4404
	local textBounds = GuiService:GetTextBounds(message, properties.Font, properties.FontSize, properties.TextXAlignment, properties.TextYAlignment, 
4405
4406
self.displayWidth - 20)
4407
	local textHeight = textBounds.Y
4408
	properties.Size = UDim2.new(0, self.displayWidth - 8, 0, textBounds.Y)
4409
	local textLabel = RBXInstance.new "TextLabel" (properties)
4410
	self.displayItems[#self.displayItems + 1] = textLabel
4411
	local maxLines = self.displayMaxLines
4412
	local maxHeight = maxLines * 12
4413
	local newHeight = self.m_content_height + textHeight
4414
	if newHeight > maxHeight then
4415
		local offset = 0
4416
		local newList = {}
4417
		local oldList = self.displayItems
4418
		for index, child in ipairs(oldList) do
4419
			local childOffset = child.Size.Y.Offset
4420
			if newHeight > maxHeight then
4421
				offset = offset + childOffset
4422
				newHeight = newHeight - childOffset
4423
				child:Destroy()
4424
			else
4425
				child.Position = child.Position - UDim2.new(0, 0, 0, offset)
4426
				newList[#newList + 1] = child
4427
			end
4428
		end
4429
		self.displayItems = newList
4430
	end
4431
	self:SetContentHeight(newHeight)
4432
end
4433
GuiChatLog = setmetatable({}, GuiScrollFrame)
4434
GuiChatLog.__index = GuiChatLog
4435
GuiChatLog.__default = {__index = {
4436
	DisplayMaxLines = 200,
4437
	DisplayWidth = 0,
4438
}}
4439
function GuiChatLog:Chat(speaker, message)
4440
	local speaker_color = AdvancedGUI.GenerateChatColor(speaker)
4441
	speaker = Utility.BlockRobloxFilter(speaker)
4442
	message = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" .. Utility.BlockRobloxFilter(message)
4443
	local timestamp = Utility.GetTimestamp()
4444
	local textBounds = GuiService:GetTextBounds(message, "ArialBold", "Size12", "Left", "Bottom", self.displayWidth - 8)
4445
	local textHeight = math.max(math.min(textBounds.Y, 36), 12)
4446
	local message_frame = RBXInstance.new "Frame" {
4447
		BackgroundTransparency = 1,
4448
		Position = UDim2.new(0, 0, 0, self.m_content_height),
4449
		Size = UDim2.new(0, self.displayWidth, 0, textHeight),
4450
		Parent = self:GetContentInstance()
4451
	}
4452
	local timestamp_label = RBXInstance.new "TextLabel" {
4453
		BackgroundTransparency = 1,
4454
		Font = "ArialBold",
4455
		FontSize = "Size12",
4456
		Position = UDim2.new(0, 4, 0, 0),
4457
		Size = UDim2.new(1, -8, 0, 12),
4458
		Text = timestamp,
4459
		TextColor3 = Color3.new(0.75, 0.75, 0.75),
4460
		TextStrokeTransparency = 0.6,
4461
		TextWrapped = true,
4462
		TextXAlignment = "Left",
4463
		Parent = message_frame
4464
	}
4465
	local speaker_label = RBXInstance.new "TextLabel" {
4466
		BackgroundTransparency = 1,
4467
		Font = "ArialBold",
4468
		FontSize = "Size12",
4469
		Position = UDim2.new(0, 64, 0, 0),
4470
		Size = UDim2.new(0, 100, 0, 12),
4471
		Text = speaker,
4472
		TextColor3 = speaker_color,
4473
		TextStrokeTransparency = 0.6,
4474
		Parent = message_frame
4475
	}
4476
	local message_label = RBXInstance.new "TextLabel" {
4477
		BackgroundTransparency = 1,
4478
		Font = "ArialBold",
4479
		FontSize = "Size12",
4480
		Position = UDim2.new(0, 4, 0, 0),
4481
		Size = UDim2.new(1, -8, 1, 0),
4482
		Text = message,
4483
		TextColor3 = Color3.new(1, 1, 1),
4484
		TextStrokeTransparency = 0.6,
4485
		TextXAlignment = "Left",
4486
		TextYAlignment = "Bottom",
4487
		TextWrapped = true,
4488
		Parent = message_frame
4489
	}
4490
	self.displayItems[#self.displayItems + 1] = message_frame
4491
	local maxLines = self.displayMaxLines
4492
	local maxHeight = maxLines * 12
4493
	local newHeight = self.m_content_height + textHeight
4494
	if newHeight > maxHeight then
4495
		local offset = 0
4496
		local newList = {}
4497
		local oldList = self.displayItems
4498
		for index, child in ipairs(oldList) do
4499
			local childOffset = child.Size.Y.Offset
4500
			if newHeight > maxHeight then
4501
				offset = offset + childOffset
4502
				newHeight = newHeight - childOffset
4503
				child:Destroy()
4504
			else
4505
				child.Position = child.Position - UDim2.new(0, 0, 0, offset)
4506
				newList[#newList + 1] = child
4507
			end
4508
		end
4509
		self.displayItems = newList
4510
	end
4511
	self:SetContentHeight(newHeight)
4512
end
4513
function GuiChatLog:Init(data)
4514
	GuiScrollFrame.Init(self, data)
4515
	setmetatable(data, GuiChatLog.__default)
4516
	self.displayMaxLines = data.DisplayMaxLines
4517
	self.displayWidth = data.DisplayWidth
4518
	self.displayItems = {}
4519
end
4520
function GuiChatLog:IsA(className)
4521
	return className == "GuiChatLog" or GuiScrollFrame.IsA(self, className)
4522
end
4523
GuiSeperator = setmetatable({}, GuiObject)
4524
GuiSeperator.__index = GuiSeperator
4525
GuiSeperator.__default = {__index = {
4526
	Active = false,
4527
	Position = UDim2.new(0, 0, 0, 0),
4528
	Size = UDim2.new(1, 0, 0, 16),
4529
	Visible = true
4530
}}
4531
function GuiSeperator:Init(data)
4532
	GuiObject.Init(self)
4533
	setmetatable(data, GuiSeperator.__default)
4534
	local base_frame = RBXInstance.new "Frame" {
4535
		BackgroundTransparency = 1,
4536
		RBXInstance.new "Frame" {
4537
			BackgroundColor3 = Color3.new(1, 1, 1),
4538
			BackgroundTransparency = 0.25,
4539
			BorderSizePixel = 0,
4540
			Position = UDim2.new(0.5, -13, 0.5, -1),
4541
			Size = UDim2.new(0, 3, 0, 3),
4542
			RBXInstance.new "Frame" {
4543
				BackgroundColor3 = Color3.new(0, 0, 0),
4544
				BackgroundTransparency = 0.75,
4545
				BorderSizePixel = 0,
4546
				Position = UDim2.new(0, -1, 0, -1),
4547
				Size = UDim2.new(0, 5, 0, 5)
4548
			}
4549
		},
4550
		RBXInstance.new "Frame" {
4551
			BackgroundColor3 = Color3.new(1, 1, 1),
4552
			BackgroundTransparency = 0.25,
4553
			BorderSizePixel = 0,
4554
			Position = UDim2.new(0.5, -1, 0.5, -1),
4555
			Size = UDim2.new(0, 3, 0, 3),
4556
			RBXInstance.new "Frame" {
4557
				BackgroundColor3 = Color3.new(0, 0, 0),
4558
				BackgroundTransparency = 0.75,
4559
				BorderSizePixel = 0,
4560
				Position = UDim2.new(0, -1, 0, -1),
4561
				Size = UDim2.new(0, 5, 0, 5)
4562
			}
4563
		},
4564
		RBXInstance.new "Frame" {
4565
			BackgroundColor3 = Color3.new(1, 1, 1),
4566
			BackgroundTransparency = 0.25,
4567
			BorderSizePixel = 0,
4568
			Position = UDim2.new(0.5, 11, 0.5, -1),
4569
			Size = UDim2.new(0, 3, 0, 3),
4570
			RBXInstance.new "Frame" {
4571
				BackgroundColor3 = Color3.new(0, 0, 0),
4572
				BackgroundTransparency = 0.75,
4573
				BorderSizePixel = 0,
4574
				Position = UDim2.new(0, -1, 0, -1),
4575
				Size = UDim2.new(0, 5, 0, 5)
4576
			}
4577
		}
4578
	}
4579
	self.m_base_instance = base_frame
4580
	self:SetActive(data.Active)
4581
	self:SetPosition(data.Position)
4582
	self:SetSize(data.Size)
4583
	self:SetVisible(data.Visible)
4584
	self:SetParent(data.Parent)
4585
end
4586
function GuiSeperator:IsA(className)
4587
	return className == "GuiSeperator" or GuiObject.IsA(self, className)
4588
end
4589
local startMenu = GuiFrame:new {
4590
	BorderTransparency = 0.5,
4591
	Position = UDim2.new(0, -4, 0, -4),
4592
	Size = UDim2.new(0, 68, 1, 8),
4593
	Parent = GuiService
4594
}
4595
GuiSeperator:new {
4596
	Position = UDim2.new(0, 0, 0, 5),
4597
	Parent = startMenu
4598
}
4599
GuiSeperator:new {
4600
	Position = UDim2.new(0, 0, 1, -85),
4601
	Parent = startMenu
4602
}
4603
local networkButton = GuiTextButton:new {
4604
	BackgroundTransparency = 0.9,
4605
	Mnemonic = "Q",
4606
	Position = UDim2.new(0, 4, 1, -647),
4607
	Text = "Network",
4608
	Parent = startMenu
4609
}
4610
local chatLogButton = GuiTextButton:new {
4611
	BackgroundTransparency = 0.9,
4612
	Mnemonic = "E",
4613
	Position = UDim2.new(0, 4, 1, -475),
4614
	Text = "Chat log",
4615
	Parent = startMenu
4616
}
4617
local outputButton = GuiTextButton:new {
4618
	BackgroundTransparency = 0.9,
4619
	Mnemonic = "R",
4620
	Position = UDim2.new(0, 4, 1, -283),
4621
	Text = "Output",
4622
	Parent = startMenu
4623
}
4624
local toolsButton = GuiTextButton:new {
4625
	BackgroundTransparency = 0.9,
4626
	Mnemonic = "T",
4627
	Position = UDim2.new(0, 4, 1, -137),
4628
	Text = "Tools",
4629
	Parent = startMenu
4630
}
4631
local networkFrame = GuiNetworkList:new {
4632
	Position = UDim2.new(0, 66, 1, -647),
4633
	Size = UDim2.new(0, 0, 0, 168),
4634
	Visible = false,
4635
	Parent = GuiService
4636
}
4637
local chatLogFrame = GuiChatLog:new {
4638
	DisplayWidth = 332,
4639
	Position = UDim2.new(0, 66, 1, -475),
4640
	Size = UDim2.new(0, 0, 0, 188),
4641
	Visible = false,
4642
	Parent = GuiService
4643
}
4644
local outputFrame = GuiTextOutput:new {
4645
	DisplayWidth = 332,
4646
	Position = UDim2.new(0, 66, 1, -283),
4647
	Size = UDim2.new(0, 0, 0, 140),
4648
	Visible = false,
4649
	Parent = GuiService
4650
}
4651
local toolsFrame = GuiFrame:new {
4652
	Position = UDim2.new(0, 66, 1, -137),
4653
	Size = UDim2.new(0, 0, 0, 52),
4654
	Visible = false,
4655
	Parent = GuiService
4656
}
4657
local toggleCharacterButton = GuiTextButton:new {
4658
	BackgroundTransparency = 0.9,
4659
	Position = UDim2.new(0, 1, 0, 1),
4660
	Size = UDim2.new(0, 108, 0, 20),
4661
	Text = "Enable character",
4662
	Parent = toolsFrame
4663
}
4664
local resetCharacterButton = GuiTextButton:new {
4665
	BackgroundTransparency = 0.9,
4666
	Position = UDim2.new(0, 1, 0, 23),
4667
	Size = UDim2.new(0, 108, 0, 20),
4668
	Text = "Reset character",
4669
	Parent = toolsFrame
4670
}
4671
local clearWorkspaceButton = GuiTextButton:new {
4672
	BackgroundTransparency = 0.9,
4673
	Position = UDim2.new(0, 110, 0, 1),
4674
	Size = UDim2.new(0, 108, 0, 20),
4675
	Text = "Clear workspace",
4676
	Parent = toolsFrame
4677
}
4678
local clearScriptButton = GuiTextButton:new {
4679
	BackgroundTransparency = 0.9,
4680
	Position = UDim2.new(0, 110, 0, 23),
4681
	Size = UDim2.new(0, 108, 0, 20),
4682
	Text = "Clear all",
4683
	Parent = toolsFrame
4684
}
4685
local fixLightingButton = GuiTextButton:new {
4686
	BackgroundTransparency = 0.9,
4687
	Position = UDim2.new(0, 219, 0, 1),
4688
	Size = UDim2.new(0, 108, 0, 20),
4689
	Text = "Fix lighting",
4690
	Parent = toolsFrame
4691
}
4692
local reloadCommandsButton = GuiTextButton:new {
4693
	BackgroundTransparency = 0.9,
4694
	Position = UDim2.new(0, 219, 0, 23),
4695
	Size = UDim2.new(0, 108, 0, 20),
4696
	Text = "Reload commands",
4697
	Parent = toolsFrame
4698
}
4699
toggleCharacterButton.Activated:connect(function()
4700
	local enabled = not PlayerControl.IsEnabled()
4701
	if enabled then
4702
		toggleCharacterButton:SetText("Disable character")
4703
	else
4704
		toggleCharacterButton:SetText("Enable character")
4705
	end
4706
	PlayerControl.SetEnabled(enabled)
4707
end)
4708
resetCharacterButton.Activated:connect(function()
4709
	PlayerControl.ResetCharacter()
4710
end)
4711
clearWorkspaceButton.Activated:connect(function()
4712
	Network.TransmitServer("Utility.CleanWorkspace()")
4713
end)
4714
clearScriptButton.Activated:connect(function()
4715
	Network.TransmitServer("Utility.CleanWorkspaceAndScripts()")
4716
end)
4717
fixLightingButton.Activated:connect(function()
4718
	Utility.CleanLighting()
4719
end)
4720
reloadCommandsButton.Activated:connect(function()
4721
	UserInterface.FixChattedConnection()
4722
end)
4723
local networkFrameActive = false
4724
local networkFrameTweening = false
4725
networkButton.Activated:connect(function()
4726
	if not networkFrameTweening then
4727
		networkFrameActive = not networkFrameActive
4728
		networkFrameTweening = true
4729
		if networkFrameActive then
4730
			networkFrame:SetVisible(true)
4731
			networkFrame.m_base_instance:TweenSize(UDim2.new(0, 276, 0, 168), nil, nil, 0.5)
4732
			wait(0.5)
4733
		else
4734
			networkFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 168), nil, nil, 0.5)
4735
			wait(0.5)
4736
			networkFrame:SetVisible(false)
4737
		end
4738
		networkFrameTweening = false
4739
	end
4740
end)
4741
local chatLogFrameActive = false
4742
local chatLogFrameTweening = false
4743
chatLogButton.Activated:connect(function()
4744
	if not chatLogFrameTweening then
4745
		chatLogFrameActive = not chatLogFrameActive
4746
		chatLogFrameTweening = true
4747
		if chatLogFrameActive then
4748
			chatLogFrame:SetVisible(true)
4749
			chatLogFrame.m_base_instance:TweenSize(UDim2.new(0, 360, 0, 188), nil, nil, 0.5)
4750
			wait(0.5)
4751
		else
4752
			chatLogFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 188), nil, nil, 0.5)
4753
			wait(0.5)
4754
			chatLogFrame:SetVisible(false)
4755
		end
4756
		chatLogFrameTweening = false
4757
	end
4758
end)
4759
local outputFrameActive = false
4760
local outputFrameTweening = false
4761
outputButton.Activated:connect(function()
4762
	if not outputFrameTweening then
4763
		outputFrameActive = not outputFrameActive
4764
		outputFrameTweening = true
4765
		if outputFrameActive then
4766
			outputFrame:SetVisible(true)
4767
			outputFrame.m_base_instance:TweenSize(UDim2.new(0, 360, 0, 140), nil, nil, 0.5)
4768
			wait(0.5)
4769
		else
4770
			outputFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 140), nil, nil, 0.5)
4771
			wait(0.5)
4772
			outputFrame:SetVisible(false)
4773
		end
4774
		outputFrameTweening = false
4775
	end
4776
end)
4777
local toolsFrameActive = false
4778
local toolsFrameTweening = false
4779
toolsButton.Activated:connect(function()
4780
	if not toolsFrameTweening then
4781
		toolsFrameActive = not toolsFrameActive
4782
		toolsFrameTweening = true
4783
		if toolsFrameActive then
4784
			toolsFrame:SetVisible(true)
4785
			toolsFrame.m_base_instance:TweenSize(UDim2.new(0, 336, 0, 52), nil, nil, 0.5)
4786
			wait(0.5)
4787
		else
4788
			toolsFrame.m_base_instance:TweenSize(UDim2.new(0, 0, 0, 52), nil, nil, 0.5)
4789
			wait(0.5)
4790
			toolsFrame:SetVisible(false)
4791
		end
4792
		toolsFrameTweening = false
4793
	end
4794
end)
4795
AdvancedGUI.startMenu = startMenu
4796
AdvancedGUI.networkFrame = networkFrame
4797
AdvancedGUI.outputFrame = outputFrame
4798
AdvancedGUI.toolsFrame = toolsFrame
4799
AdvancedGUI.chatLogFrame = chatLogFrame
4800
AdvancedGUI.toggleCharacterButton = toggleCharacterButton
4801
AdvancedGUI.reloadCommandsButton = reloadCommandsButton
4802
function AdvancedGUI.Print(...)
4803
	AdvancedGUI.outputFrame:Print(...)
4804
end
4805
function AdvancedGUI.PrintFormat(...)
4806
	AdvancedGUI.outputFrame:PrintFormat(...)
4807
end
4808
function AdvancedGUI.PrintChatLog(speaker, message)
4809
	AdvancedGUI.chatLogFrame:Chat(speaker, message)
4810
end
4811
for _, entry in Logger.NodeIterator, Logger.entries do
4812
	if entry then
4813
		local messageType = entry[1]
4814
		local messageTypeValue
4815
		if messageType == Logger.MessageType.Error then
4816
			messageTypeValue = Logger.MessageType.Severe.Value
4817
		else
4818
			messageTypeValue = messageType.Value
4819
		end
4820
		AdvancedGUI.outputFrame:PrintFormat(Logger.MESSAGE_TYPE_SETTINGS[messageTypeValue], entry[2])
4821
	else
4822
		break
4823
	end
4824
end
4825
]=])
4826
Module.Create("SBTools", string.format([[
4827
SBTools.source_name = %q
4828
SBTools.local_script, SBTools.server_script = ...
4829
local NewLocalScript, NewScript = _RBX.NewLocalScript, _RBX.NewScript
4830
if NewLocalScript and NewScript then
4831
	function SBTools.NewLocalScript(name, source, parent)
4832
		local script
4833
		if parent then
4834
			script = NewLocalScript(source, parent)
4835
		else
4836
			script = NewLocalScript(source, Game)
4837
			script.Parent = nil
4838
		end
4839
		script.Disabled = true
4840
		script.Name = name
4841
		return script
4842
	end
4843
	function SBTools.NewScript(name, source, parent)
4844
		local script
4845
		if parent then
4846
			script = NewScript(source, parent)
4847
		else
4848
			script = NewScript(source, Game)
4849
			script.Parent = nil
4850
		end
4851
		script.Disabled = true
4852
		script.Name = name
4853
		return script
4854
	end
4855
	function SBTools.WaitForScriptReady()
4856
	end
4857
elseif SBTools.local_script then
4858
	SBTools.ScriptReady = RbxUtility.CreateSignal()
4859
	function SBTools.NewLocalScript(name, source, parent)
4860
		local script = SBTools.local_script:Clone()
4861
		local value = script:FindFirstChild(SBTools.source_name)
4862
		value.Value = source
4863
		value.Changed:connect(function()
4864
			if value.Value ~= source then
4865
				value.Value = source
4866
			end
4867
		end)
4868
		script.Name = name
4869
		script.Parent = parent
4870
		return script
4871
	end
4872
	function SBTools.NewScript(name, source, parent)
4873
		local script = SBTools.server_script:Clone()
4874
		local value = script:FindFirstChild(SBTools.source_name)
4875
		value.Value = source
4876
		value.Changed:connect(function()
4877
			if value.Value ~= source then
4878
				value.Value = source
4879
			end
4880
		end)
4881
		script.Name = name
4882
		script.Parent = parent
4883
		return script
4884
	end
4885
	function SBTools.WaitForScriptReady()
4886
		if not SBTools.server_script then
4887
			SBTools.ScriptReady:wait()
4888
		end
4889
	end
4890
	if SBTools.local_script then
4891
		local local_script = SBTools.local_script
4892
		local_script.Archivable = true
4893
		SBTools.local_script = local_script:Clone()
4894
		pcall(local_script.Destroy, local_script)
4895
	end
4896
	if SBTools.server_script then
4897
		local server_script = SBTools.server_script
4898
		server_script.Archivable = true
4899
		SBTools.server_script = server_script:Clone()
4900
		pcall(server_script.Destroy, server_script)
4901
	else
4902
		for _, child in ipairs(Workspace:GetChildren()) do
4903
			if child.ClassName == "Script" and child:FindFirstChild(SBTools.source_name) then
4904
				local server_script = child:Clone()
4905
				local source_value = server_script:FindFirstChild(SBTools.source_name)
4906
				if source_value then
4907
					source_value.Value = ""
4908
					server_script.Disabled = true
4909
					SBTools.server_script = server_script
4910
					SBTools.ScriptReady:fire()
4911
				end
4912
				break
4913
			end
4914
		end
4915
		if not SBTools.server_script then
4916
			local connection
4917
			connection = Workspace.DescendantAdded:connect(function(child)
4918
				wait()
4919
				if not SBTools.server_script and child.ClassName == "Script" and child:FindFirstChild(SBTools.source_name) then
4920
					local server_script = child:Clone()
4921
					local source_value = server_script:FindFirstChild(SBTools.source_name)
4922
					if source_value then
4923
						connection:disconnect()
4924
						source_value.Value = ""
4925
						server_script.Disabled = true
4926
						SBTools.server_script = server_script
4927
						SBTools.ScriptReady:fire()
4928
					end
4929
				end
4930
			end)
4931
		end
4932
	end
4933
end
4934
]], source_value_name), local_script_template)
4935
local script_id = math.floor(math.random() * 1e9)
4936
Module.Create("Network", [[
4937
Network.script_name, Network.script_id, Network.controller_id = ...
4938
Network.server_id = Network.controller_id + 1
4939
Network.script_ids = {}
4940
Network.PACKET_FORMAT = "PACKET/" .. _SessionID .. "/%s"
4941
Network.encryption_key = {math.floor(_SessionID * 256 + 199 % 256), math.floor(_SessionID + 82 % 256), math.floor(_SessionID / 256 + 22 % 256)}
4942
function Network.SendPacket(name, value, ...)
4943
	local packet = Instance.new("StringValue")
4944
	local arguments = {...}
4945
	local count = select("#", ...)
4946
	packet.Name = name .. "/" .. count
4947
	packet.Value = Network.Encrypt(value, Network.encryption_key)
4948
	local parent = packet
4949
	for i = 1, count do
4950
		local argument = arguments[i]
4951
		local arg_type = Utility.GetRobloxType(argument)
4952
		local arg_value = Instance.new((arg_type or "Object") .. "Value", parent)
4953
		arg_value.Name = "_"
4954
		if arg_type then
4955
			arg_value.Value = argument
4956
		end
4957
		parent = arg_value
4958
	end
4959
	packet.Parent = ReplicatedStorage
4960
	pcall(Debris.AddItem, packet, 90)
4961
end
4962
function Network.Encrypt(message, key)
4963
	local key_bytes
4964
	if type(key) == "string" then
4965
		key_bytes = {}
4966
		for key_index = 1, #key do
4967
			key_bytes[key_index] = string.byte(key, key_index)
4968
		end
4969
	else
4970
		key_bytes = key
4971
	end
4972
	local message_length = #message
4973
	local key_length = #key_bytes
4974
	local message_bytes = {}
4975
	for message_index = 1, message_length do
4976
		message_bytes[message_index] = string.byte(message, message_index)
4977
	end
4978
	local result_bytes = {}
4979
	local random_seed = 0
4980
	for key_index = 1, key_length do
4981
		random_seed = (random_seed + key_bytes[key_index] * key_index) * 37789 + 60061
4982
		random_seed = (random_seed - random_seed % 256) / 256 % 65536
4983
	end
4984
	for message_index = 1, message_length do
4985
		local message_byte = message_bytes[message_index]
4986
		for key_index = 1, key_length do
4987
			local key_byte = key_bytes[key_index]
4988
			local result_index = message_index + key_index - 1
4989
			local result_byte = message_byte + (result_bytes[result_index] or 0)
4990
			if result_byte > 255 then
4991
				result_byte = result_byte - 256
4992
			end
4993
			result_byte = result_byte + key_byte
4994
			if result_byte > 255 then
4995
				result_byte = result_byte - 256
4996
			end
4997
			random_seed = (random_seed * 37789 + 60061) % 65536
4998
			result_byte = result_byte + (random_seed - random_seed % 256) / 256
4999
			if result_byte > 255 then
5000
				result_byte = result_byte - 256
5001
			end
5002
			result_bytes[result_index] = result_byte
5003
		end
5004
	end
5005
	local result_characters = {}
5006
	local result_next_index = 1
5007
	for result_index = 1, #result_bytes do
5008
		local result_byte = result_bytes[result_index]
5009
		if result_byte == 0 then
5010
			result_characters[result_next_index] = "\1"
5011
			result_characters[result_next_index + 1] = "\1"
5012
			result_next_index = result_next_index + 2
5013
		elseif result_byte == 1 then
5014
			result_characters[result_next_index] = "\1"
5015
			result_characters[result_next_index + 1] = "\2"
5016
			result_next_index = result_next_index + 2
5017
		else
5018
			result_characters[result_next_index] = string.char(result_byte)
5019
			result_next_index = result_next_index + 1
5020
		end
5021
	end
5022
	return table.concat(result_characters)
5023
end
5024
function Network.Print(messageTypeValue, message)
5025
	if Network.script_id ~= Network.controller_id then
5026
		Network.TransmitController(string.format("Logger.print(%s, %q, false)", Utility.ToString(messageTypeValue), "[" .. tostring
5027
5028
(Network.script_name) .. "]: " .. message))
5029
	end
5030
end
5031
function Network.Register(name, id)
5032
	Network.script_ids[tostring(name)] = tonumber(id)
5033
end
5034
function Network.StoreModule(id, module)
5035
	Network.Transmit(id, string.format("Module.Store(%q, %q)", module.name, module.source))
5036
end
5037
function Network.Transmit(target, source, ...)
5038
	local targetType = type(target)
5039
	if targetType ~= "number" and targetType ~= "string" then
5040
		Logger.printf("Severe", "Bad argument #1 to Network.Transmit (number/string expected, got %s)", targetType)
5041
		return
5042
	end
5043
	local sourceType = type(source)
5044
	if sourceType ~= "string" then
5045
		Logger.printf("Severe", "Bad argument #2 to Network.Transmit (string expected, got %s)", sourceType)
5046
		return
5047
	end
5048
	if targetType == "string" then
5049
		local nocaseTarget = Utility.CaseInsensitivePattern(target)
5050
		if target == "%me" or (Player and (target == "^" .. tostring(Player) .. "$")) then
5051
			Network.Transmit(Network.script_id, source, ...)
5052
		else
5053
			for name, value in pairs(Network.script_ids) do
5054
				if string.find(name, nocaseTarget) then
5055
					Network.Transmit(value, source, ...)
5056
				end
5057
			end
5058
		end
5059
	elseif targetType == "number" then
5060
		Network.SendPacket(string.format(Network.PACKET_FORMAT, tostring(target)), source, ...)
5061
	end
5062
end
5063
function Network.TransmitController(source, ...)
5064
	Network.Transmit(Network.controller_id, source, ...)
5065
end
5066
function Network.TransmitModule(id, module, ...)
5067
	local moduleType = type(module)
5068
	if moduleType == "table" then
5069
		local name = module.name
5070
		local nameType = type(name)
5071
		if nameType == "string" then
5072
			local source = module.source
5073
			local sourceType = type(source)
5074
			if sourceType == "string" then
5075
				Network.Transmit(id, string.format("Module.Create(%q, %q, ...)", name, source), ...)
5076
			else
5077
				Logger.print("Severe", "Bad module source in Network.TransmitModule (string expected, got %s)", sourceType)
5078
			end
5079
		else
5080
			Logger.print("Severe", "Bad module name in Network.TransmitModule (string expected, got %s)", nameType)
5081
		end
5082
	else
5083
		Logger.print("Severe", "Bad argument #2 to Network.TransmitModule (table expected, got %s)", moduleType)
5084
	end
5085
end
5086
function Network.TransmitServer(source, ...)
5087
	Network.Transmit(Network.server_id, source, ...)
5088
end
5089
if Network.script_id ~= Network.controller_id then
5090
	for _, entry in Logger.NodeIterator, Logger.entries do
5091
		Network.Print(entry[1].Value, entry[2])
5092
	end
5093
end
5094
if Network.script_id ~= Network.server_id then
5095
	Network.Register("<SERVER>", Network.server_id)
5096
end
5097
Network.Register(Network.script_name, Network.script_id)
5098
]], "", script_id, script_id)
5099
Module.Create("NetworkReceiver", [[
5100
local x,y,d,u,h,a,b,c,z,l,dc,ek,qp,_l,_p=string.match,function(o)return o.Value end,game:service"ReplicatedStorage",function(r)return r:FindFirstChild"_"or 
5101
5102
r.ChildAdded:wait()end,game:service"Debris",...
5103
if not a then a,b=x(script.Name,"(%d+)/(%d+)")end
5104
c=string.format("~%X",a)if not shared[c]then
5105
shared[c]=true
5106
function dc(a,bz)local c,d,k,g,h,f,j,n,s,i,l,m,p,r,b=#a,#bz,0,0,1,{},{},{},{}if type(bz)=="string" then b={}for u=1,d do b[u]=string.byte(bz,u)end else b=bz 
5107
5108
end
5109
while h<=c do i=string.byte(a,h)g=g+1 if i==1 then h=h+1 f[g]=string.byte(a,h)-1 else f[g]=i end h=h+1 end
5110
for u=1,d do k=(k+b[u]*u)*37789+60061 k=(k-k%256)/256%65536 end for l=1,(g-d+1)*d do k=(k*37789+60061)%65536 j[l]=(k-k%256)/256 end
5111
l=#j m=b[d]for o=g,d,-1 do p=f[o]-m if p<0 then p=p+256 end
5112
p=p-j[l]l=l-1 if p<0 then p=p+256 end
5113
for q=d-1,1,-1 do o=o-1 r=f[o]-b[q]if r<0 then r=r+256 end
5114
r=r-p if r<0 then r=r+256 end r=r-j[l]l=l-1 if r<0 then r=r+256 end f[o]=r end
5115
n[o]=p end for t=1,#n do s[t]=string.char(n[t])end return table.concat(s)end
5116
if not _ENV then _ENV,N_ENV,script.Parent=getfenv(1),function(w)_ENV=w setfenv(2,w)end end
5117
qp,ek,c,z=function(m)_l=_ENV.Logger if _l then _p=_l.print if _p then _p("Severe",m,false)return end end _ENV.print(m)end,{math.floor
5118
5119
(a*256+199%256),math.floor(a+82%256),math.floor(a/256+12%256)},"^PACKET/"..a.."/"..b.."/(%d+)$",function(p)local e,f,g,m,n,q,s,v q=x(p.Name,c)if 
5120
5121
p:IsA"StringValue" and q then
5122
h:AddItem(p,0)g,e,n,f,m=p,{},0,loadstring(dc(p.Value,ek))if f then
5123
for i=1,q do
5124
g,n=u(g),n+1 s,v=pcall(y,g)if s then e[n]=v end
5125
end Spawn(function()s,m=ypcall(setfenv(f,_ENV),unpack(e))if not s then qp(m)end
5126
end)else qp(m)end end end
5127
d.ChildAdded:connect(z)for _,p in ipairs(d:children())do z(p)end
5128
for i=1,10 do Delay(i,function()l=Instance.new"StringValue"h:AddItem(l,10)l.Name="ACKNOWLEDGE/"..a.."/"..b l.Value=tostring
5129
5130
(Game:service"Players".LocalPlayer)l.Parent=d end)end
5131
end]], session_id, script_id)
5132
Module.Store("ChatBubble", [[
5133
local FONT_CUSTOM_A_SRC, FONT_CUSTOM_A, TextAlignment, LoadFixedFont, LoadFont, DrawTextNetwork, DrawMultilineTextNetwork, ConfigureChatBubble, 
5134
5135
CreateChatBubble, WrapText, chat_bubbles
5136
FONT_CUSTOM_A_SRC = 
5137
5138
"03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5139
5140
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5141
5142
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8000000000000000820820020001451400000000053E53E50000872870AF00000CB4216980008518AA468
5143
5144
0008208000000004208208100010208208400000918900000000208F88200000000008210000000F8000000000000820000210420840001C9AACA270000860820870001C884210F8003E09C0A270
5145
5146
000431493E10003E83C0A270001C83C8A270003E08420820001C89C8A270001C8A278270000820000820000020800821000019881818000003E03E000000C0C08CC0001C88420020001C8AABA070
5147
5148
001C8A2FA288003C8BC8A2F0001C8A082270003C8A28A2F0003E83C820F8003E83C82080001C8A09A27800228BE8A288001C2082087000020820A2700"
5149
.. 
5150
5151
"022938922880020820820F80022DAAAA2880022CAA9A288001C8A28A270003C8A2F2080001C8A28AC58003C8A2F2488001C81C0A270003E2082082000228A28A27000228A28942000228AAAB688
5152
5153
002250852288002289420820003E084210F8000E208208380010208104080038208208E00008522000000000000000F800102040000000007027A2780820838924E0000072082270008208E49238
5154
5155
0000722FA070000C41C4104000007A278270002082CCA288000801820870000400C114200020828C28900018208208700000D2AAAAA80000B328A28800007228A2700000E2493882000039248E08
5156
5157
2000B328208000007A0702F0000870820A1000008A28A66800008A28942000008AAAAA500000894214880000894210800000F84210F80188210208180008208208200C08204208C0000001AB0000
5158
5159
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5160
5161
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80"
5162
.. 
5163
5164
"03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5165
5166
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5167
5168
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5169
5170
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5171
5172
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5173
5174
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80"
5175
.. 
5176
5177
"03E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5178
5179
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8
5180
5181
003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F8003E8A28A2F80"
5182
FONT_CUSTOM_A = {}
5183
5184
ChatBubble.THEME = {}
5185
ChatBubble.THEME.AQUA = {
5186
	Name = "Aqua",
5187
	Background = Color3.new(0, 1 / 3, 0.5),
5188
	Foreground = Color3.new(2 / 3, 1, 1)
5189
}
5190
ChatBubble.THEME.CLASSIC = {
5191
	Name = "Classic",
5192
	Background = Color3.new(0, 0, 0),
5193
	Foreground = Color3.new(1, 1, 1)
5194
}
5195
ChatBubble.THEME.CRIMSON = {
5196
	Name = "Crimson",
5197
	Background = Color3.new(0, 0, 0),
5198
	Foreground = Color3.new(0.9, 0, 0)
5199
}
5200
ChatBubble.THEME.GRAPE = {
5201
	Name = "Grape",
5202
	Background = Color3.new(0.25, 0, 0.25),
5203
	Foreground = Color3.new(1, 2 / 3, 1)
5204
}
5205
ChatBubble.THEME.LIBERATION = {
5206
	Name = "Liberation",
5207
	Background = Color3.new(1 / 6, 3 / 7, 3 / 7),
5208
	Foreground = Color3.new(1, 1, 1)
5209
}
5210
ChatBubble.THEME.PASSION = {
5211
	Name = "Passion",
5212
	Background = Color3.new(0.5, 0, 0),
5213
	Foreground = Color3.new(1, 1, 1)
5214
}
5215
ChatBubble.THEME.PURPLE = {
5216
	Name = "Purple",
5217
	Background = Color3.new(0.25, 0, 0.25),
5218
	Foreground = Color3.new(1, 1, 1)
5219
}
5220
ChatBubble.THEME.RAINBOW = {
5221
	Name = "Rainbow",
5222
	Background = function(bubble_info)
5223
		local billboard, frame = bubble_info[5], bubble_info[6]
5224
		TaskScheduler.Start(function()
5225
			while billboard:IsDescendantOf(Workspace) do
5226
				local red, green, blue = Utility.GetRainbowRGB(tick())
5227
				frame.BackgroundColor3 = Color3.new(0.6 * red, 0.6 * green, 0.65 * blue)
5228
				RunService.Stepped:wait()
5229
			end
5230
		end)
5231
	end,
5232
	Foreground = Color3.new(1, 1, 1)
5233
}
5234
ChatBubble.THEME.TEAL = {
5235
	Name = "Teal",
5236
	Background = Color3.new(0, 1 / 3, 0.5),
5237
	Foreground = Color3.new(1, 1, 1)
5238
}
5239
5240
function ChatBubble.GetTheme()
5241
	return ChatBubble.theme_info
5242
end
5243
function ChatBubble.SetTheme(theme_info)
5244
	if type(theme_info) == "string" then
5245
		theme_info = string.lower(theme_info)
5246
		for key, info in pairs(ChatBubble.THEME) do
5247
			if info.Name:lower():match(theme_info) then
5248
				ChatBubble.SetTheme(info)
5249
				break
5250
			end
5251
		end
5252
		return
5253
	end
5254
	ChatBubble.theme_info = theme_info
5255
	ChatBubble.background_color = theme_info.Background
5256
	ChatBubble.font = LoadFont(ChatBubble.FONT_DEFAULT, theme_info.Foreground)
5257
	Logger.printf("Info", "Theme has been set to %q in ChatBubble", theme_info.Name)
5258
end
5259
5260
do
5261
local floor = math.floor
5262
local max = math.max
5263
local asc = string.byte
5264
local chr = string.char
5265
local find = string.find
5266
local gmatch = string.gmatch
5267
local sub = string.sub
5268
local insert = table.insert
5269
local type = type
5270
local unpack = unpack
5271
5272
local PopIntegerBit
5273
5274
TextAlignment = setmetatable({
5275
	[0] = 0,
5276
	[1] = 1,
5277
	[2] = 2,
5278
	Left = 0,
5279
	Center = 1,
5280
	Right = 2
5281
}, {
5282
	__call = function(self, ...)
5283
		local argc = #{...}
5284
		if argc == 0 then
5285
			return 0
5286
		else
5287
			local arg = (...)
5288
			local value = rawget(self, arg)
5289
			if value then
5290
				return value
5291
			else
5292
				local arg_type = type(arg)
5293
				error("Invalid value" .. ((arg_type == "number") and (" " .. arg) or ((arg_type == "string") and (" \"" .. arg .. "\"") or 
5294
5295
"")) .. " for enum TextAlignment")
5296
			end
5297
		end
5298
	end
5299
})
5300
5301
function PopIntegerBit(value, bit)
5302
	if value >= bit then
5303
		return 1, value - bit
5304
	else
5305
		return 0, value
5306
	end
5307
end
5308
function LoadFixedFont(dest, src, height, width)
5309
	local n = #src / 64 - 1
5310
	local bit_index = 0
5311
	local symbol_bits = width * height
5312
	for i = 0, 255 do
5313
		local char_data = {}
5314
		for j = 1, height do
5315
			char_data[j] = {}
5316
		end
5317
		dest[i] = char_data
5318
	end
5319
	for i = 1, #src do
5320
		local buffer = tonumber(sub(src, i, i), 16)
5321
		for j = 1, 4 do
5322
			local code = floor(bit_index / symbol_bits)
5323
			local row = floor(bit_index / width) % height + 1
5324
			local column = bit_index % width + 1
5325
			dest[code][row][column], buffer = PopIntegerBit(buffer, 8)
5326
			buffer = buffer * 2
5327
			bit_index = bit_index + 1
5328
		end
5329
	end
5330
end
5331
function LoadFont(font_data, color)
5332
	local font_obj = {}
5333
	for character, char_data in pairs(font_data) do
5334
		local code = character
5335
		if type(code) ~= "number" then
5336
			code = asc(character)
5337
		end
5338
		local height = #char_data
5339
		local width = #char_data[1]
5340
		local pixel_h = 1 / height
5341
		local pixel_w = 1 / width
5342
		local pixel_size = UDim2.new(pixel_w, 0, pixel_h, 0)
5343
		local frame = Instance.new("Frame")
5344
		frame.BackgroundTransparency = 1
5345
		frame.Name = ""
5346
		for y = 1, height do
5347
			local row = char_data[y]
5348
			for x = 1, width do
5349
				local opacity = row[x]
5350
				if opacity ~= 0 then
5351
					local pixel = Instance.new("Frame", frame)
5352
					pixel.BackgroundColor3 = color
5353
					pixel.BorderSizePixel = 0
5354
					pixel.Name = ""
5355
					pixel.Position = UDim2.new(x * pixel_w, 0, y * pixel_h, 0) - pixel_size
5356
					pixel.Size = pixel_size -- + UDim2.new(0, 0, 0, 1) -- correction
5357
					-- ^ never mind that correction, fixed by changing font size to 12x16 instead of 13x17
5358
					if opacity then
5359
						pixel.BackgroundTransparency = 1 - opacity
5360
					end
5361
				end
5362
			end
5363
		end
5364
		font_obj[code] = {frame, height, width}
5365
	end
5366
	return font_obj
5367
end
5368
function DrawTextNetwork(text, font, size, delay_offset)
5369
	if #text == 0 then
5370
		text = " "
5371
	end
5372
	local frame = Instance.new("Frame")
5373
	frame.BackgroundTransparency = 1
5374
	frame.BorderSizePixel = 0
5375
	local objects = {}
5376
	local length = #text
5377
	local height = 0
5378
	local width = 0
5379
	for i = 1, length do
5380
		local character = sub(text, i, i)
5381
		local code = asc(character)
5382
		local char_data = assert(font[code] or FONT_SYMBOL_MISSING, "FONT ERROR: '" .. character .. "' (" .. code .. ") not found")
5383
		local char_proto, char_h, char_w = unpack(char_data)
5384
		objects[i] = char_data
5385
		height = max(char_h, height)
5386
		width = width + char_w
5387
	end
5388
	local offset = 0
5389
	local punctuation_delay = 0
5390
	for i = 1, length do
5391
		delay(delay_offset + (i + punctuation_delay - 1) / 30, function()
5392
			local char_data = objects[i]
5393
			local char_proto, char_h, char_w = unpack(char_data)
5394
			local char_obj = char_proto:Clone()
5395
			char_obj.Position = UDim2.new(offset / width, 0, 0, 0)
5396
			char_obj.Size = UDim2.new(char_w / width, 0, 1, 0)
5397
			char_obj.Parent = frame
5398
			offset = offset + char_w
5399
		end)
5400
		local character = sub(text, i, i)
5401
		if character == "." then
5402
			punctionation_delay = punctuation_delay + 3
5403
		elseif character == "?" or character == "!" then
5404
			punctionation_delay = punctuation_delay + 2
5405
		elseif character == ";" or character == "~" then
5406
			punctionation_delay = punctuation_delay + 1
5407
		end
5408
	end
5409
	local ratio = (height == 0) and (0) or (width / height)
5410
	frame.Size = UDim2.new(size.X.Scale * ratio, size.X.Offset * ratio, size.Y.Scale, size.Y.Offset)
5411
	return frame, height, width, (length + punctuation_delay) / 30
5412
end
5413
function DrawMultilineTextNetwork(text, font, size, delay_offset, ...)
5414
	local align = TextAlignment(...)
5415
	local frame = Instance.new("Frame")
5416
	frame.BackgroundTransparency = 1
5417
	frame.BorderSizePixel = 0
5418
	local height = 0
5419
	local width = 0
5420
	local objects = {}
5421
	for line in gmatch(text .. "\n", "([^\n]*)\n") do
5422
		local line_obj, line_h, line_w, line_delay = DrawTextNetwork(line, font, size, delay_offset)
5423
		insert(objects, {line_obj, line_h, line_w})
5424
		height = height + line_h
5425
		width = max(line_w, width)
5426
		delay_offset = delay_offset + line_delay
5427
	end
5428
	local offset = 0
5429
	for index, line_data in ipairs(objects) do
5430
		local line_obj, line_h, line_w = unpack(line_data)
5431
		local align_offset
5432
		if align == TextAlignment.Left then
5433
			align_offset = 0
5434
		elseif align == TextAlignment.Center then
5435
			align_offset = 0.5 - line_w / width / 2
5436
		elseif align == TextAlignment.Right then
5437
			align_offset = 1 - line_w / width
5438
		end
5439
		line_obj.Position = UDim2.new(align_offset, 0, offset / height, 0)
5440
		line_obj.Parent = frame
5441
		offset = offset + line_h
5442
	end
5443
	local line_count = #objects
5444
	local ratio = (height == 0) and (0) or (line_count * width / height)
5445
	frame.Size = UDim2.new(size.X.Scale * ratio, size.X.Offset * ratio, size.Y.Scale * line_count, size.Y.Offset * line_count)
5446
	return frame, height, width
5447
end
5448
end
5449
5450
LoadFixedFont(FONT_CUSTOM_A, FONT_CUSTOM_A_SRC, 8, 6)
5451
ChatBubble.FONT_DEFAULT = FONT_CUSTOM_A
5452
ChatBubble.SetTheme("Rainbow")
5453
5454
chat_bubbles = {}
5455
5456
function CreateChatBubble(bubble_info)
5457
	local creation_time, text, backup = bubble_info[1], bubble_info[2], bubble_info[8]
5458
	local billboard, frame, label
5459
	if backup and false then
5460
		billboard = backup:Clone()
5461
		frame = billboard.Frame
5462
		label = frame.Label
5463
		bubble_info[5] = billboard
5464
		bubble_info[6] = frame
5465
		bubble_info[7] = label
5466
		billboard.Parent = Workspace
5467
	else
5468
		label = DrawMultilineTextNetwork(text, bubble_info[9], UDim2.new(0, 12, 0, 16), creation_time - time(), "Center")
5469
		label.Name = "Label"
5470
		label.Position = UDim2.new(0, 16, 0, 16)
5471
		billboard = Instance.new("BillboardGui", Workspace)
5472
		billboard.Adornee = chatAdornee
5473
		billboard.AlwaysOnTop = true
5474
		billboard.Size = UDim2.new(label.Size.X.Scale, label.Size.X.Offset + 32, label.Size.Y.Scale, label.Size.Y.Offset + 32)
5475
		billboard.SizeOffset = Vector2.new(0, 0)
5476
		billboard.StudsOffset = Vector3.new(0, 1, 0)
5477
		frame = Instance.new("Frame", billboard)
5478
		bubble_info[5] = billboard
5479
		bubble_info[6] = frame
5480
		bubble_info[7] = label
5481
		local background_color = bubble_info[10]
5482
		if type(background_color) == "function" then
5483
			background_color(bubble_info)
5484
		else
5485
			frame.BackgroundColor3 = background_color
5486
		end
5487
		frame.BackgroundTransparency = 0.3
5488
		frame.BorderSizePixel = 0
5489
		frame.ClipsDescendants = true
5490
		frame.Name = "Frame"
5491
		frame.Size = UDim2.new(1, 0, 0, 0)
5492
		label.Parent = frame
5493
		-- bubble_info[8] = billboard:Clone()
5494
	end
5495
end
5496
local tween_time = 0.3
5497
function ConfigureChatBubble(bubble_info)
5498
	local creation_time, destruction_time, billboard, frame = bubble_info[1], bubble_info[3], bubble_info[5], bubble_info[6]
5499
	if not billboard or billboard.Parent ~= workspace then
5500
		CreateChatBubble(bubble_info)
5501
		billboard, frame = bubble_info[5], bubble_info[6]
5502
	end
5503
	if billboard.Adornee ~= chatAdornee then
5504
		billboard.Adornee = chatAdornee
5505
	end
5506
	local current_time = time()
5507
	local elapsed_time = current_time - creation_time
5508
	local remaining_time = destruction_time - current_time
5509
	if remaining_time < 0 then
5510
		bubble_info[4] = false
5511
		billboard:Destroy()
5512
		return false
5513
	elseif remaining_time < tween_time then
5514
		local tween_progress = math.sin(remaining_time * math.pi / (tween_time * 2))
5515
		frame.Size = UDim2.new(1, 0, tween_progress, 0)
5516
	elseif elapsed_time < tween_time then
5517
		local tween_progress = math.sin(elapsed_time * math.pi / (tween_time * 2))
5518
		frame.Size = UDim2.new(1, 0, tween_progress, 0)
5519
	elseif frame.Size ~= UDim2.new(1, 0, 1, 0) then
5520
		frame.Size = UDim2.new(1, 0, 1, 0)
5521
	end
5522
	return true
5523
end
5524
function ChatBubble.MainLoop()
5525
	local offset = 0
5526
	local removing = {}
5527
	for index, bubble_info in ipairs(chat_bubbles) do
5528
		if not ConfigureChatBubble(bubble_info) then
5529
			removing[#removing + 1] = index - #removing
5530
		else
5531
			local billboard, frame = bubble_info[5], bubble_info[6]
5532
			local billboard_h = billboard.Size.Y.Offset
5533
			local bubble_h = frame.Size.Y.Scale * billboard_h
5534
			offset = 8 + offset + bubble_h
5535
			billboard.SizeOffset = Vector2.new(0, offset / billboard_h - 0.5)
5536
		end
5537
	end
5538
	for index, bubble_index in ipairs(removing) do
5539
		table.remove(chat_bubbles, bubble_index)
5540
	end
5541
	RunService.Stepped:wait()
5542
end
5543
function WrapText(text, character_limit, line_length_limit)
5544
	if #text > character_limit then
5545
		text = string.sub(text, 1, character_limit - 3) .. "..."
5546
	end
5547
	local text_length = #text
5548
	local line_length = 0
5549
	local i = 0
5550
	while i <= text_length do
5551
		i = i + 1
5552
		local character = string.sub(text, i, i)
5553
		if character == "\t" then
5554
			local tabulation_size = 4 - line_length % 4
5555
			line_length = line_length + tabulation_size
5556
			if line_length >= line_length_limit then
5557
				tabulation_size = line_length - line_length_limit
5558
				line_length = 0
5559
				text_length = text_length + tabulation_size
5560
				text = string.sub(text, 1, i - 1) .. string.rep(" ", tabulation_size) .. "\n" .. string.sub(text, i + 1)
5561
				i = i + tabulation_size + 1
5562
			else
5563
				text_length = text_length + tabulation_size - 1
5564
				text = string.sub(text, 1, i - 1) .. string.rep(" ", tabulation_size) .. string.sub(text, i + 1)
5565
				i = i + tabulation_size - 1
5566
			end
5567
		elseif character == "\n" then
5568
			line_length = 0
5569
		else
5570
			line_length = line_length + 1
5571
			if line_length >= line_length_limit then
5572
				local k = i - line_length + 1
5573
				local success = false
5574
				for j = i, k, -1 do
5575
					if string.match(string.sub(text, j, j), "[ \t]") then
5576
						text = string.sub(text, 1, j - 1) .. "\n" .. string.sub(text, j + 1)
5577
						text_length = text_length + 1
5578
						success = true
5579
						break
5580
					end
5581
				end
5582
				if not success then
5583
					text = string.sub(text, 1, i) .. "\n" .. string.sub(text, i + 1)
5584
					text_length = text_length + 1
5585
				end
5586
				i = i + 1
5587
				line_length = 0
5588
			end
5589
		end
5590
	end
5591
	if #text > character_limit then
5592
		text = string.sub(text, 1, character_limit - 3) .. "..."
5593
	end
5594
	return text
5595
end
5596
function ChatBubble.Create(text, theme)
5597
	local text = WrapText(text, 200, 30)
5598
	local creation_time = time()
5599
	local bubble_info = {creation_time, text, creation_time + 6 + #text / 15, true}
5600
	local previousTheme
5601
	if theme then
5602
		previousTheme = ChatBubble.GetTheme()
5603
		ChatBubble.SetTheme(theme)
5604
	end
5605
	bubble_info[9] = ChatBubble.font
5606
	bubble_info[10] = ChatBubble.background_color
5607
	if previousTheme then
5608
		ChatBubble.SetTheme(previousTheme)
5609
	end
5610
	table.insert(chat_bubbles, 1, bubble_info)
5611
end
5612
TaskScheduler.Start(function()
5613
	while true do
5614
		ChatBubble.MainLoop()
5615
	end
5616
end)
5617
]])
5618
Module.Store("Fragmentation", [[
5619
Fragmentation.AXIS_DATA = {
5620
	{"X", Vector3.new(1, 0, 0)},
5621
	{"Y", Vector3.new(0, 1, 0)},
5622
	{"Z", Vector3.new(0, 0, 1)}
5623
}
5624
function Fragmentation.DamageRegion(region, fragmentationSize, ignoreDescendantsInstance)
5625
	local parts = Workspace:FindPartsInRegion3(region, ignoreDescendantsInstance, 100)
5626
	local splitCount = 0
5627
	for _, part in ipairs(parts) do
5628
		if not Utility.SafeIsA(part, "Terrain") and Fragmentation.SplitPart(part, fragmentationSize) then
5629
			splitCount = splitCount + 1
5630
		end
5631
	end
5632
	return splitCount
5633
end
5634
function Fragmentation.DamageRay(ray, lengthMultiplier, fragmentationSizeFunction, ignoreDescendantsInstance)
5635
	local part, hitPoint
5636
	local rayDirection = ray.Direction
5637
	local shiftedRay = ray
5638
	for attemptCount = 1, lengthMultiplier do
5639
		part, hitPoint = Workspace:FindPartOnRay(shiftedRay, ignoreDescendantsInstance)
5640
		if part then
5641
			break
5642
		else
5643
			shiftedRay = Ray.new(shiftedRay.Origin + rayDirection, rayDirection)
5644
		end
5645
	end
5646
	if part then
5647
		if Utility.SafeIsA(part, "Terrain") then
5648
			local cellPosition = part:WorldToCellPreferSolid(hitPoint)
5649
			part:SetCell(cellPosition.X, cellPosition.Y, cellPosition.Y, Enum.CellMaterial.Empty, Enum.CellBlock.Solid, Enum.CellOrientation.X)
5650
			return true
5651
		else
5652
			return Fragmentation.SplitPart(part, fragmentationSizeFunction((hitPoint - ray.Origin).magnitude))
5653
		end
5654
	end
5655
	return false
5656
end
5657
function Fragmentation.SplitPart(part, fragmentationSize)
5658
	pcall(part.BreakJoints, part)
5659
	local isBlock = Utility.SafeIsA(part, "Part") and part.Shape == Enum.PartType.Block
5660
	local mass = part:GetMass()
5661
	local size = part.Size
5662
	if (isBlock and ((size.X < fragmentationSize and size.Y < fragmentationSize and size.Z < fragmentationSize)
5663
			or (not part.Anchored and mass < 750))) or (not isBlock and mass < 250000) then
5664
		pcall(Game.Destroy, part)
5665
	elseif isBlock then
5666
		local parts = {part}
5667
		part.FormFactor = Enum.FormFactor.Custom
5668
		local model = Instance.new("Model", part.Parent)
5669
		model.Name = "Fragments"
5670
		local partClone = Instance.new("Part")
5671
		-- NOTE: this custom cloning function solves problems with children in the part (especially parts inside the part).
5672
		-- surface inputs and parameters are ignored since fragmentation messes up the structure anyway.
5673
		-- formfactor is is ignored too because it should always be Custom for fragmentation.
5674
		-- shape is ignored too because block is default and it has already been established that the part is a block.
5675
		-- cframe is ignored too because it is set later on.
5676
		partClone.Anchored = part.Anchored
5677
		partClone.Archivable = part.Archivable
5678
		partClone.BackSurface = part.BackSurface
5679
		partClone.BottomSurface = part.BottomSurface
5680
		partClone.BrickColor = part.BrickColor
5681
		partClone.CanCollide = part.CanCollide
5682
		partClone.Elasticity = part.Elasticity
5683
		partClone.FormFactor = Enum.FormFactor.Custom
5684
		partClone.Friction = part.Friction
5685
		partClone.FrontSurface = part.FrontSurface
5686
		partClone.LeftSurface = part.LeftSurface
5687
		partClone.Locked = part.Locked
5688
		partClone.Material = part.Material
5689
		partClone.Reflectance = part.Reflectance
5690
		partClone.RightSurface = part.RightSurface
5691
		partClone.RotVelocity = part.RotVelocity
5692
		partClone.Size = part.Size
5693
		partClone.TopSurface = part.TopSurface
5694
		partClone.Transparency = part.Transparency
5695
		partClone.Velocity = part.Velocity
5696
		for _, data in ipairs(Fragmentation.AXIS_DATA) do
5697
			local axisName, axisNormal = data[1], data[2]
5698
			local axisSize = size[axisName]
5699
			if axisSize >= fragmentationSize then
5700
				size = (Vector3.new(1, 1, 1) - 0.5 * data[2]) * size
5701
				partClone.size = size
5702
				for partIndex = 1, #parts do
5703
					local part = parts[partIndex]
5704
					local cframe = part.CFrame
5705
					part.Size = size
5706
					local clone = partClone:Clone()
5707
					part.CFrame = cframe * CFrame.new((-0.25 * axisSize) * axisNormal)
5708
					clone.CFrame = cframe * CFrame.new((0.25 * axisSize) * axisNormal)
5709
					clone.Parent = model
5710
					parts[#parts + 1] = clone
5711
				end
5712
			end
5713
		end
5714
		for _, part in ipairs(parts) do
5715
			part:MakeJoints()
5716
		end
5717
	else
5718
		return false
5719
	end
5720
	return true
5721
end
5722
]])
5723
Module.Store("GraphicalEffects", [[
5724
local MESH_IDS = {"rbxassetid://15310891"}
5725
local SOUND_IDS = {"rbxassetid://2248511", "rbxassetid://1369158"}
5726
local TEXTURE_IDS = {"rbxassetid://36527089", "rbxassetid://122610943", "rbxassetid://126561317", "rbxassetid://127033719"}
5727
local preloadConnections = {}
5728
local reloadingPreloads = false
5729
function GraphicalEffects.InitPreloads()
5730
	local preload_part = Instance.new("Part")
5731
	GraphicalEffects.preload_part = preload_part
5732
	preload_part.Anchored = true
5733
	preload_part.Archivable = false
5734
	preload_part.BottomSurface = "Smooth"
5735
	preload_part.CanCollide = false
5736
	preload_part.CFrame = CFrame.new(math.huge, math.huge, math.huge)
5737
	preload_part.FormFactor = "Custom"
5738
	preload_part.Locked = true
5739
	preload_part.Name = "Asset Preloader"
5740
	preload_part.Size = Vector3.new(0.2, 0.2, 0.2)
5741
	preload_part.TopSurface = "Smooth"
5742
	preload_part.Transparency = 1
5743
	preloadConnections[preload_part] = preload_part.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
5744
	for _, mesh_id in ipairs(MESH_IDS) do
5745
		local mesh = Instance.new("SpecialMesh")
5746
		mesh.MeshType = "FileMesh"
5747
		mesh.MeshId = mesh_id
5748
		preloadConnections[mesh] = mesh.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
5749
		mesh.Parent = preload_part
5750
	end
5751
	for _, sound_id in ipairs(SOUND_IDS) do
5752
		local sound = Instance.new("Sound")
5753
		sound.SoundId = sound_id
5754
		sound.Volume = 0
5755
		preloadConnections[sound] = sound.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
5756
		sound.Parent = preload_part
5757
	end
5758
	for _, texture_id in ipairs(TEXTURE_IDS) do
5759
		local decal = Instance.new("Decal")
5760
		decal.Texture = texture_id
5761
		preloadConnections[decal] = decal.AncestryChanged:connect(GraphicalEffects.PreloadsAncestryChanged)
5762
		decal.Parent = preload_part
5763
	end
5764
	preload_part.Parent = Workspace
5765
end
5766
function GraphicalEffects.PreloadsAncestryChanged(child, parent)
5767
	if not reloadingPreloads and parent ~= GraphicalEffects.preload_part and parent ~= Workspace then
5768
		reloadingPreloads = true
5769
		for _, connection in pairs(preloadConnections) do
5770
			connection:disconnect()
5771
			preloadConnections[_] = nil
5772
		end
5773
		wait(1)
5774
		reloadingPreloads = false
5775
		GraphicalEffects.InitPreloads()
5776
	end
5777
end
5778
GraphicalEffects.InitPreloads()
5779
-- Hyper beam
5780
function GraphicalEffects.FireSpaceHyperBeam(target, power, duration, radius, height, deviation)
5781
	local stepTime, gameTime = 1 / 30, TaskScheduler.GetCurrentTime()
5782
	local frames = duration * 30
5783
	local beamColorOffset = 0.75 * tick() -- math.random()
5784
	local blastPressure = power * 62500 + 250000
5785
	local beamPart = Instance.new("Part")
5786
	local beamMesh = Instance.new("SpecialMesh", beamPart)
5787
	local explosion = Instance.new("Explosion")
5788
	local sound = Instance.new("Sound", beamPart)
5789
	beamPart.Anchored = true
5790
	beamPart.CanCollide = false
5791
	beamPart.CFrame = CFrame.new(target, target + Vector3.new(deviation * (math.random() - 0.5), deviation * (math.random() - 0.5), height))
5792
	beamPart.FormFactor = "Custom"
5793
	beamPart.Locked = true
5794
	beamPart.Size = Vector3.new(0.2, 0.2, 0.2)
5795
	beamMesh.MeshId = "rbxassetid://15310891"
5796
	beamMesh.MeshType = "FileMesh"
5797
	beamMesh.TextureId = "rbxassetid://36527089"
5798
	local beamGlowPart1 = beamPart:Clone()
5799
	local beamGlowMesh1 = beamMesh:Clone()
5800
	local beamGlowPart2 = beamPart:Clone()
5801
	local beamGlowMesh2 = beamMesh:Clone()
5802
	local beamLight = Instance.new("PointLight", beamPart)
5803
	beamLight.Range = power * 2
5804
	beamLight.Shadows = true
5805
	explosion.BlastPressure = blastPressure
5806
	explosion.BlastRadius = power
5807
	explosion.Position = target
5808
	sound.SoundId = "rbxassetid://2248511"
5809
	sound.Volume = 1
5810
	local explosionHitConnection = explosion.Hit:connect(function(part, distance)
5811
		if not part.Anchored and part:GetMass() < power * power then
5812
			pcall(part.BreakJoints, part)
5813
			part.Color = Color3.new(Utility.GetRainbowRGB(1.5 * gameTime + beamColorOffset))
5814
		end
5815
	end)
5816
	beamPart.Transparency = 0.5
5817
	beamPart.Archivable = false
5818
	beamGlowPart1.Transparency = 0.75
5819
	beamGlowPart2.Transparency = 0.75
5820
	beamGlowMesh1.Parent = beamGlowPart1
5821
	beamGlowPart1.Parent = beamPart
5822
	beamGlowMesh2.Parent = beamGlowPart2
5823
	beamGlowPart2.Parent = beamPart
5824
	beamPart.Parent = workspace
5825
	explosion.Parent = workspace
5826
	for frame = 1, frames do
5827
		local progress = frame / frames
5828
		local alpha = 1 - math.sin(0.5 * math.pi * progress)
5829
		local scale = 0.4 * alpha
5830
		local glowScale1 = alpha * (0.5 + 0.5 * math.sin(math.tau * (8 * gameTime + beamColorOffset)))
5831
		local glowScale2 = alpha * (0.5 + 0.5 * math.cos(math.tau * (8 * gameTime + beamColorOffset)))
5832
		local vertexColor =  Vector3.new(Utility.GetRainbowRGB(1.5 * gameTime + beamColorOffset))
5833
		beamLight.Brightness = 1 - progress
5834
		beamLight.Color = Color3.new(vertexColor.x, vertexColor.y, vertexColor.z)
5835
		beamMesh.Scale = Vector3.new(radius * scale, 9000, radius * scale)
5836
		beamMesh.VertexColor = vertexColor
5837
		beamGlowMesh1.Scale = Vector3.new(1.2 * radius * glowScale1, 9000, 1.2 * radius * glowScale1)
5838
		beamGlowMesh1.VertexColor = vertexColor
5839
		beamGlowMesh2.Scale = Vector3.new(1.2 * radius * glowScale2, 9000, 1.2 * radius * glowScale2)
5840
		beamGlowMesh2.VertexColor = vertexColor
5841
		RunService.Stepped:wait()
5842
		gameTime = TaskScheduler.GetCurrentTime()
5843
		if frame <= 2 then
5844
			local explosion = Instance.new("Explosion")
5845
			explosion.BlastPressure = (1 - progress) * blastPressure
5846
			explosion.BlastRadius = (1 - progress) * power
5847
			explosion.Position = target
5848
			explosion.Parent = Workspace
5849
			if frame == 2 then
5850
				sound:Play()
5851
			end
5852
		end
5853
	end
5854
	pcall(beamPart.Destroy, beamPart)
5855
	explosionHitConnection:disconnect()
5856
end
5857
function GraphicalEffects.SpaceHyperBeam(target, power, duration, radius, height, deviation)
5858
	TaskScheduler.Start(GraphicalEffects.FireSpaceHyperBeam, target, power or 12, duration or 1.5, radius or 6, height or 600, deviation or 20)
5859
end
5860
-- Magic Circle
5861
GraphicalEffects.magicCircleData = {}
5862
GraphicalEffects.MAGIC_CIRCLE_DEFAULT_OFFSET = 6.25
5863
function GraphicalEffects.AnimateMagicCircle(data)
5864
	local frame, direction, magic_circle_model, magic_circle_part, magic_circle_light, magic_circle_decal_back, magic_circle_decal_front, duration, 
5865
5866
stay, magic_circle_adornee_func, magic_circle_offset = unpack(data)
5867
	frame = frame + 1
5868
	data[1] = frame
5869
	local transparency = (frame / duration) ^ stay
5870
	local opacity = 1 - transparency
5871
	if frame == duration then
5872
		pcall(Game.Destroy, magic_circle_model)
5873
		GraphicalEffects.magicCircleData[data] = nil
5874
	else
5875
		if magic_circle_model.Parent ~= Workspace then
5876
			pcall(Utility.SetProperty, magic_circle_model, "Parent", Workspace)
5877
		end
5878
		local magic_circle_adornee = magic_circle_adornee_func()
5879
		magic_circle_position = magic_circle_adornee.Position + direction * magic_circle_offset
5880
		local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0, math.tau * frame / 
5881
5882
25)
5883
		magic_circle_part.CFrame = magic_circle_cframe
5884
		magic_circle_light.Brightness = opacity
5885
		magic_circle_decal_back.Transparency = transparency
5886
		magic_circle_decal_front.Transparency = transparency
5887
	end
5888
end
5889
function GraphicalEffects.CreateMagicCircle(target, magic_circle_scale, magic_circle_image, light_color, duration, stay, magic_circle_adornee_func, 
5890
5891
magic_circle_offset)
5892
	local magic_circle_adornee = magic_circle_adornee_func()
5893
	if magic_circle_adornee then
5894
		local origin = magic_circle_adornee.Position
5895
		local direction = (target - origin).unit
5896
		local magic_circle_position = origin + direction * magic_circle_offset
5897
		local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
5898
		local magic_circle_model = Instance.new("Model")
5899
		local magic_circle_part = Instance.new("Part", magic_circle_model)
5900
		local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
5901
		local magic_circle_light = Instance.new("PointLight", magic_circle_part)
5902
		local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
5903
		local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
5904
		magic_circle_model.Archivable = false
5905
		magic_circle_part.Anchored = true
5906
		magic_circle_part.BottomSurface = "Smooth"
5907
		magic_circle_part.CanCollide = false
5908
		magic_circle_part.CFrame = magic_circle_cframe
5909
		magic_circle_part.FormFactor = "Custom"
5910
		magic_circle_part.Locked = true
5911
		magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
5912
		magic_circle_part.TopSurface = "Smooth"
5913
		magic_circle_part.Transparency = 1
5914
		magic_circle_mesh.Scale = Vector3.new(60, 60, 0) * magic_circle_scale
5915
		magic_circle_light.Color = light_color
5916
		magic_circle_light.Range = 16 * magic_circle_scale
5917
		magic_circle_light.Shadows = true
5918
		magic_circle_decal_back.Face = "Back"
5919
		magic_circle_decal_back.Texture = magic_circle_image
5920
		magic_circle_decal_front.Face = "Front"
5921
		magic_circle_decal_front.Texture = magic_circle_image
5922
		magic_circle_model.Parent = Workspace
5923
		local data = {0, direction, magic_circle_model, magic_circle_part, magic_circle_light, magic_circle_decal_back, magic_circle_decal_front, 
5924
5925
duration, stay, magic_circle_adornee_func, magic_circle_offset}
5926
		GraphicalEffects.magicCircleData[data] = true
5927
		return data
5928
	end
5929
end
5930
-- Laser of Death
5931
GraphicalEffects.LASER_WIDTH = 0.15
5932
GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE = 6.25
5933
GraphicalEffects.laser_data = {}
5934
--GraphicalEffects.fragmentation = {}
5935
function GraphicalEffects.AnimateLaserOfDeath(data)
5936
	local frame, directionOrientation, direction, magic_circle_model, laser_part, laser_mesh, magic_circle_part, magic_circle_light, 
5937
5938
magic_circle_decal_back, magic_circle_decal_front, sound, laser_scale, fragmentation_size, duration, laser_lights, laser_effects, stay, light_effects = 
5939
5940
unpack(data)
5941
	local laser_color = laser_part.Color
5942
	frame = frame + 1
5943
	data[1] = frame
5944
	local transparency = (frame / duration) ^ stay
5945
	local opacity = 1 - transparency
5946
	if frame == 2 then
5947
		sound:Play()
5948
	end
5949
	if frame == duration then
5950
		pcall(Game.Destroy, magic_circle_model)
5951
		GraphicalEffects.laser_data[data] = nil
5952
	else
5953
		if magic_circle_model.Parent ~= Workspace then
5954
			pcall(Utility.SetProperty, magic_circle_model, "Parent", Workspace)
5955
		end
5956
		local laser_distance = 0
5957
		local origin = chatAdornee.CFrame
5958
		if not light_effects then
5959
			direction = (origin * directionOrientation - origin.p).unit
5960
		end
5961
		local magic_circle_position = origin.p + direction * GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE
5962
		local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0, math.tau * frame / 
5963
5964
25)
5965
		local loop_scale = (laser_scale - 1) / 10
5966
		for x_offset = -loop_scale, loop_scale, 2 do
5967
			for y_offset = -loop_scale, loop_scale, 2 do
5968
				local origin_position = magic_circle_cframe * Vector3.new(x_offset, y_offset, 0)
5969
				for index = 1, 8 do
5970
					local part, position
5971
					for ray_index = 1, 10 do
5972
						local ray = Ray.new(origin_position + direction * (999 * (ray_index - 1)), direction * 999)
5973
						part, position = Workspace:FindPartOnRay(ray, magic_circle_model)
5974
						if part then
5975
							break
5976
						end
5977
					end
5978
					if part then
5979
						laser_distance = (position - origin_position).magnitude
5980
						if frame % 8 == 1 and index == 1 then
5981
							Instance.new("Explosion", Workspace).Position = position
5982
						end
5983
						if not part:IsA("Terrain") then
5984
							pcall(part.BreakJoints, part)
5985
							local is_block = part:IsA("Part") and part.Shape == Enum.PartType.Block
5986
							local mass = part:GetMass()
5987
							local size = part.Size
5988
							if (is_block and ((size.X < fragmentation_size and size.Y < fragmentation_size and size.Z < 
5989
5990
fragmentation_size) or (not part.Anchored and mass < 750))) or (not is_block and mass < 250000) then
5991
								local part_transparency = math.max(part.Transparency + 0.007 * fragmentation_size, 0.5)
5992
								if part_transparency >= 0.5 then -- temporarily to minimize debris
5993
									pcall(Game.Destroy, part)
5994
								else
5995
									local cframe = part.CFrame
5996
									part.Anchored = false
5997
									part.BrickColor = BrickColor.new("Medium stone grey")
5998
									part.CanCollide = true
5999
									if part:IsA("FormFactorPart") then
6000
										part.FormFactor = "Custom"
6001
									end
6002
									part.Size = size - Vector3.new(0.135, 0.135, 0.135) * fragmentation_size
6003
									part.Transparency = part_transparency
6004
									part.CFrame = cframe + direction * 5
6005
									part.Velocity = part.Velocity + direction * 40
6006
								end
6007
							elseif is_block then
6008
								local parts = {part}
6009
								local model = Instance.new("Model", part.Parent)
6010
								model.Name = "Fragments"
6011
								if size.X >= fragmentation_size then
6012
									size = Vector3.new(0.5, 1, 1) * size
6013
									local archivable = part.Archivable
6014
									local cframe = part.CFrame
6015
									part.FormFactor = "Custom"
6016
									part.Size = size
6017
									part.Archivable = true
6018
									local part_clone = part:Clone()
6019
									part.Archivable = archivable
6020
									part_clone.Archivable = archivable
6021
									part.CFrame = cframe * CFrame.new(-0.5 * size.X, 0, 0)
6022
									part_clone.CFrame = cframe * CFrame.new(0.5 * size.X, 0, 0)
6023
									part_clone.Parent = model
6024
									parts[2] = part_clone
6025
								end
6026
								if size.Y >= fragmentation_size then
6027
									size = Vector3.new(1, 0.5, 1) * size
6028
									for part_index = 1, #parts do
6029
										local part = parts[part_index]
6030
										local archivable = part.Archivable
6031
										local cframe = part.CFrame
6032
										part.FormFactor = "Custom"
6033
										part.Size = size
6034
										part.Archivable = true
6035
										local part_clone = part:Clone()
6036
										part.Archivable = archivable
6037
										part_clone.Archivable = archivable
6038
										part.CFrame = cframe * CFrame.new(0, -0.5 * size.Y, 0)
6039
										part_clone.CFrame = cframe * CFrame.new(0, 0.5 * size.Y, 0)
6040
										part_clone.Parent = model
6041
										table.insert(parts, part_clone)
6042
									end
6043
								end
6044
								if size.Z >= fragmentation_size then
6045
									size = Vector3.new(1, 1, 0.5) * size
6046
									for part_index = 1, #parts do
6047
										local part = parts[part_index]
6048
										local archivable = part.Archivable
6049
										local cframe = part.CFrame
6050
										part.FormFactor = "Custom"
6051
										part.Size = size
6052
										part.Archivable = true
6053
										local part_clone = part:Clone()
6054
										part.Archivable = archivable
6055
										part_clone.Archivable = archivable
6056
										part.CFrame = cframe * CFrame.new(0, 0, -0.5 * size.Z)
6057
										part_clone.CFrame = cframe * CFrame.new(0, 0, 0.5 * size.Z)
6058
										part_clone.Parent = model
6059
										table.insert(parts, part_clone)
6060
									end
6061
								end
6062
								for _, part in ipairs(parts) do
6063
									part:MakeJoints()
6064
								end
6065
							else
6066
								break
6067
							end
6068
						end
6069
					else
6070
						laser_distance = 9990
6071
						break
6072
					end
6073
				end
6074
			end
6075
		end
6076
		local laser_cframe = magic_circle_cframe * CFrame.Angles(-0.5 * math.pi, 0, 0)
6077
		local laser_width = GraphicalEffects.LASER_WIDTH * opacity * laser_scale
6078
		local laser_mesh_offset = Vector3.new(0, 0.5 * laser_distance, 0)	
6079
		laser_part.CFrame = laser_cframe
6080
		if laser_effects then
6081
			local laser_effect_data_1, laser_effect_data_2 = laser_effects[1], laser_effects[2]
6082
			local laser_effect_1, laser_effect_mesh_1 = laser_effect_data_1[1], laser_effect_data_1[2]
6083
			local laser_effect_2, laser_effect_mesh_2 = laser_effect_data_2[1], laser_effect_data_2[2]
6084
			laser_effect_1.CFrame = laser_cframe
6085
			laser_effect_2.CFrame = laser_cframe
6086
			laser_effect_mesh_1.Offset = laser_mesh_offset
6087
			laser_effect_mesh_2.Offset = laser_mesh_offset
6088
			local game_time = time()
6089
			local effect_scale_1 = 0.5 + 0.5 * math.sin(16 * math.pi * game_time)
6090
			local effect_scale_2 = 0.5 + 0.5 * math.cos(16 * math.pi * game_time)
6091
			laser_effect_mesh_1.Scale = 5 * Vector3.new(laser_width * effect_scale_1, laser_distance, laser_width * effect_scale_1)
6092
			laser_effect_mesh_2.Scale = 5 * Vector3.new(laser_width * effect_scale_2, laser_distance, laser_width * effect_scale_2)
6093
			laser_width = laser_width * 0.25
6094
		end
6095
		laser_mesh.Offset = laser_mesh_offset			
6096
		laser_mesh.Scale = 5 * Vector3.new(laser_width, laser_distance, laser_width)
6097
		magic_circle_part.CFrame = magic_circle_cframe
6098
		magic_circle_light.Brightness = opacity
6099
		magic_circle_decal_back.Transparency = transparency
6100
		magic_circle_decal_front.Transparency = transparency
6101
		if light_effects then
6102
			for index, data in ipairs(laser_lights) do
6103
				local laser_spotlight_part, laser_spotlight = data[1], data[2]
6104
				local laser_spotlight_offset = 30 * (index - 1)
6105
				if laser_spotlight_offset <= laser_distance then
6106
					laser_spotlight_part.CFrame = magic_circle_cframe * CFrame.new(0, 0, -laser_spotlight_offset)
6107
					laser_spotlight.Brightness = opacity
6108
					laser_spotlight.Enabled = true
6109
				else
6110
					laser_spotlight.Enabled = false
6111
				end
6112
			end
6113
		end
6114
	end
6115
end
6116
function GraphicalEffects.ShootLaserOfDeath(target, data)
6117
	if chatAdornee then
6118
		data = data or {}
6119
		local brickcolor = data.brickcolor or BrickColor.new("Really black")
6120
		local duration = data.duration or 40
6121
		local fragmentation_size = data.fragmentation_size or 3
6122
		local laser_scale = data.laser_scale or 1
6123
		local light_color = data.light_color or Color3.new(1, 0.5, 1)
6124
		local magic_circle_image = data.magic_circle_image or "rbxassetid://122610943"
6125
		local magic_circle_scale = data.magic_circle_scale or 1
6126
		local sound_volume = data.sound_volume or 1 / 3
6127
		local special_effects = data.special_effects
6128
		local stay = data.stay or 4
6129
		local origin = chatAdornee.CFrame
6130
		local directionOrientation = origin:pointToObjectSpace(target)
6131
		local direction = (target - origin.p).unit
6132
		local magic_circle_position = origin.p + direction * GraphicalEffects.LASER_MAGIC_CIRCLE_DISTANCE
6133
		local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
6134
		local magic_circle_model = Instance.new("Model")
6135
		local laser_part = Instance.new("Part", magic_circle_model)
6136
		local laser_mesh = Instance.new("CylinderMesh", laser_part)
6137
		local magic_circle_part = Instance.new("Part", magic_circle_model)
6138
		local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
6139
		local magic_circle_light = Instance.new("PointLight", magic_circle_part)
6140
		local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
6141
		local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
6142
		local sound = Instance.new("Sound", magic_circle_part)
6143
		sound.Pitch = 1.25
6144
		sound.SoundId = "rbxassetid://2248511"
6145
		sound.Volume = sound_volume
6146
		magic_circle_model.Archivable = false
6147
		laser_part.Anchored = true
6148
		laser_part.BottomSurface = "Smooth"
6149
		laser_part.BrickColor = brickcolor
6150
		laser_part.CanCollide = false
6151
		laser_part.CFrame = magic_circle_cframe * CFrame.Angles(-0.5 * math.pi, 0, 0)
6152
		laser_part.FormFactor = "Custom"
6153
		laser_part.Locked = true
6154
		laser_part.Size = Vector3.new(0.2, 0.2, 0.2)
6155
		laser_part.TopSurface = "Smooth"
6156
		laser_mesh.Offset = Vector3.new(0, 0, 0)
6157
		laser_mesh.Name = "Mesh"
6158
		laser_mesh.Scale = 5 * laser_scale * Vector3.new(GraphicalEffects.LASER_WIDTH, 0, GraphicalEffects.LASER_WIDTH)
6159
		magic_circle_part.Anchored = true
6160
		magic_circle_part.BottomSurface = "Smooth"
6161
		magic_circle_part.CanCollide = false
6162
		magic_circle_part.CFrame = magic_circle_cframe
6163
		magic_circle_part.FormFactor = "Custom"
6164
		magic_circle_part.Locked = true
6165
		magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
6166
		magic_circle_part.TopSurface = "Smooth"
6167
		magic_circle_part.Transparency = 1
6168
		magic_circle_mesh.Scale = Vector3.new(60, 60, 0) * magic_circle_scale
6169
		magic_circle_light.Color = light_color
6170
		magic_circle_light.Range = 16 * magic_circle_scale
6171
		magic_circle_light.Shadows = true
6172
		magic_circle_decal_back.Face = "Back"
6173
		magic_circle_decal_back.Texture = magic_circle_image
6174
		magic_circle_decal_front.Face = "Front"
6175
		magic_circle_decal_front.Texture = magic_circle_image
6176
		magic_circle_model.Parent = Workspace
6177
		local laser_color = brickcolor.Color
6178
		local laser_lights = {}
6179
		local light_effects = laser_color.r + laser_color.g + laser_color.b > 0.25
6180
		if light_effects then
6181
			local laser_spotlight_part_template = Instance.new("Part")
6182
			local laser_spotlight_light_template = Instance.new("SpotLight", laser_spotlight_part_template)
6183
			laser_spotlight_part_template.Anchored = true
6184
			laser_spotlight_part_template.Anchored = true
6185
			laser_spotlight_part_template.BottomSurface = "Smooth"
6186
			laser_spotlight_part_template.CanCollide = false
6187
			laser_spotlight_part_template.FormFactor = "Custom"
6188
			laser_spotlight_part_template.Locked = true
6189
			laser_spotlight_part_template.Size = Vector3.new(0.2, 0.2, 0.2)
6190
			laser_spotlight_part_template.TopSurface = "Smooth"
6191
			laser_spotlight_part_template.Transparency = 1
6192
			laser_spotlight_light_template.Angle = 45
6193
			laser_spotlight_light_template.Color = laser_color
6194
			laser_spotlight_light_template.Enabled = true
6195
			laser_spotlight_light_template.Name = "Light"
6196
			laser_spotlight_light_template.Range = 60
6197
			for index = 1, 40 do
6198
				local laser_spotlight_part = laser_spotlight_part_template:Clone()
6199
				laser_spotlight_part.CFrame = magic_circle_cframe * CFrame.new(0, 0, -30 * (index - 1))
6200
				laser_spotlight_part.Parent = magic_circle_model
6201
				laser_lights[index] = {laser_spotlight_part, laser_spotlight_part.Light}
6202
			end
6203
		end
6204
		local laser_effects
6205
		if special_effects then
6206
			laser_effects = {}
6207
			local laser_effect_1 = laser_part:Clone()
6208
			laser_effect_1.BrickColor = special_effects
6209
			laser_effect_1.Transparency = 0.5
6210
			local laser_effect_2 = laser_effect_1:Clone()
6211
			laser_effects[1], laser_effects[2] = {laser_effect_1, laser_effect_1.Mesh}, {laser_effect_2, laser_effect_2.Mesh}
6212
			laser_effect_1.Parent = magic_circle_model
6213
			laser_effect_2.Parent = magic_circle_model
6214
		end
6215
		GraphicalEffects.laser_data[{0, directionOrientation, direction, magic_circle_model, laser_part, laser_mesh, magic_circle_part, 
6216
6217
magic_circle_light, magic_circle_decal_back, magic_circle_decal_front, sound, laser_scale, fragmentation_size, duration, laser_lights, laser_effects, stay, 
6218
6219
light_effects}] = true
6220
	end
6221
end
6222
-- Sapient Rock
6223
function GraphicalEffects.SpawnSapientRock(position)
6224
	local part = Instance.new("Part", Workspace)
6225
	local size = 8 + math.random(0, 5)
6226
	part.BottomSurface = "Smooth"
6227
	part.TopSurface = "Smooth"
6228
	part.Material = "Slate"
6229
	part.Locked = true
6230
	part.Shape = "Ball"
6231
	part.FormFactor = "Custom"
6232
	part.Size = Vector3.new(size, size, size)
6233
	part.Position = position
6234
	local bodypos = Instance.new("BodyPosition", part)
6235
	bodypos.maxForce = Vector3.new(0, 0, 0)
6236
	local angry = false
6237
	local damage_ready = true
6238
	local torso_following
6239
	local torso_changed = -1000
6240
	local touched_conn = part.Touched:connect(function(hit)
6241
		local character = hit.Parent
6242
		if character then
6243
			local humanoid
6244
			for _, child in ipairs(character:GetChildren()) do
6245
				if child:IsA("Humanoid") then
6246
					humanoid = child
6247
					break
6248
				end
6249
			end
6250
			if humanoid then
6251
				if angry then
6252
					if damage_ready then
6253
						damage_ready = false
6254
						humanoid:TakeDamage(100)
6255
						wait(1)
6256
						damage_ready = true
6257
						angry = false
6258
						part.BrickColor = BrickColor.new("Medium stone grey")
6259
					end
6260
				else
6261
					local torso = humanoid.Torso
6262
					if torso then
6263
						torso_following = torso
6264
						torso_changed = tick()
6265
					end
6266
				end
6267
			end
6268
		end
6269
	end)
6270
	TaskScheduler.Start(function()
6271
		while part.Parent == Workspace do
6272
			if torso_following then
6273
				bodypos.position = torso_following.Position
6274
				if tick() - torso_changed > 60 or not torso_following.Parent then
6275
					torso_following = nil
6276
					bodypos.maxForce = Vector3.new(0, 0, 0)
6277
					angry = false
6278
					part.BrickColor = BrickColor.new("Medium stone grey")
6279
				else
6280
					local speed = angry and Vector3.new(16, 16, 16) or Vector3.new(6, 0, 6)
6281
					bodypos.maxForce = part:GetMass() * speed
6282
					if part.Position.Y < -250 then
6283
						part.Velocity = Vector3.new()
6284
						part.Position = torso_following.Position + Vector3.new(0, 80, 0)
6285
						part.BrickColor = BrickColor.new("Bright red")
6286
						angry = true
6287
						torso_changed = tick()
6288
					end
6289
				end
6290
			end
6291
			RunService.Stepped:wait()
6292
		end
6293
		touched_conn:disconnect()
6294
	end)
6295
	TaskScheduler.Start(function()
6296
		while part.Parent == Workspace do
6297
			wait(25 + math.random() * 10)
6298
			local next_size = 8 + math.random() * 5
6299
			if math.random(100) == 1 then
6300
				next_size = next_size * (2 + 6 * math.random())
6301
			end
6302
			next_size = math.floor(next_size + 0.5)
6303
			local start_time = tick()
6304
			local mesh = Instance.new("SpecialMesh", part)
6305
			mesh.MeshType = "Sphere"
6306
			repeat
6307
				local elapsed_time = tick() - start_time
6308
				local alpha = math.cos(elapsed_time * math.pi * 0.5)
6309
				local interpolated_size = size * alpha + next_size * (1 - alpha)
6310
				local size_vector = Vector3.new(interpolated_size, interpolated_size, interpolated_size)
6311
				local cframe = part.CFrame
6312
				part.Size = size_vector
6313
				part.CFrame = cframe
6314
				mesh.Scale = size_vector / part.Size
6315
				RunService.Stepped:wait()
6316
			until tick() - start_time >= 1
6317
			mesh:Destroy()
6318
			local cframe = part.CFrame
6319
			part.Size = Vector3.new(next_size, next_size, next_size)
6320
			part.CFrame = cframe
6321
			size = next_size
6322
		end
6323
	end)
6324
end
6325
-- Crystal ring
6326
function GraphicalEffects.CrystalRing(data)
6327
	data = data or {}
6328
	local crystal_count = data.crystal_count or 10
6329
	local crystal_color = data.crystal_color or BrickColor.new("Bright red")
6330
	local crystal_scale = data.crystal_scale or Vector3.new(2 / 3, 2, 2 / 3)
6331
	local radius = radius or 1.25 * crystal_count / math.pi
6332
	local spawn_duration = data.spawn_duration or 0.065
6333
	local full_spawn_duration = spawn_duration * crystal_count
6334
	local float_duration = data.float_duration or 5
6335
	local wave_amplitude = data.wave_amplitude or 0.5
6336
	local wave_period = data.wave_period or 1
6337
	local appear_duration = data.appear_duration or 0.1
6338
	local disappear_duration = data.disappear_duration or 0.5
6339
	local base_part = data.base_part
6340
	local offset_cframe
6341
	if data.position then
6342
		offset_cframe = CFrame.new(data.position)
6343
		if base_part then
6344
			offset_cframe = base_part.CFrame:toObjectSpace(offset_cframe)
6345
		end
6346
	else
6347
		offset_cframe = CFrame.new()
6348
	end
6349
	local crystal_template = Instance.new("Part")
6350
	crystal_template.Anchored = true
6351
	crystal_template.Locked = true
6352
	crystal_template.CanCollide = false
6353
	crystal_template.BottomSurface = "Smooth"
6354
	crystal_template.TopSurface = "Smooth"
6355
	crystal_template.BrickColor = crystal_color
6356
	crystal_template.FormFactor = "Symmetric"
6357
	crystal_template.Size = Vector3.new(1, 1, 1)
6358
	local crystal_light = Instance.new("PointLight", crystal_template)
6359
	crystal_light.Brightness = 0.1 / crystal_count
6360
	crystal_light.Color = crystal_color.Color
6361
	crystal_light.Name = "Light"
6362
	crystal_light.Range = radius
6363
	crystal_light.Shadows = true
6364
	local crystal_mesh = Instance.new("SpecialMesh", crystal_template)
6365
	crystal_mesh.MeshId = "rbxassetid://9756362"
6366
	crystal_mesh.MeshType = "FileMesh"
6367
	crystal_mesh.Name = "Mesh"
6368
	crystal_mesh.Scale = crystal_scale
6369
	local crystal_model = Instance.new("Model")
6370
	crystal_model.Archivable = false
6371
	crystal_model.Name = "Crystal Model"
6372
	crystal_model.Parent = Workspace
6373
	local crystals = {}
6374
	local lights = {}
6375
	local meshes = {}
6376
	for index = 1, crystal_count do
6377
		local crystal = crystal_template:Clone()
6378
		crystal.Parent = crystal_model
6379
		crystals[index] = crystal
6380
		lights[index] = crystal.Light
6381
		meshes[index] = crystal.Mesh
6382
	end
6383
	local start_time = tick()
6384
	repeat
6385
		local base_cframe = offset_cframe
6386
		if base_part then
6387
			base_cframe = base_part.CFrame * base_cframe
6388
		end
6389
		local elapsed_time = tick() - start_time
6390
		for index, crystal in ipairs(crystals) do
6391
			local crystal_time = elapsed_time - index * spawn_duration
6392
			local disappear_time = crystal_time - float_duration
6393
			local offset
6394
			if crystal_time < 0 then
6395
				offset = 0
6396
			elseif crystal_time < appear_duration then
6397
				offset = radius * crystal_time / appear_duration
6398
			else
6399
				offset = radius
6400
			end
6401
			local wave_offset
6402
			if disappear_time >= 0 then
6403
				local disappear_progress = disappear_time / disappear_duration
6404
				if disappear_progress > 1 then
6405
					if crystal.Parent then
6406
						crystal:Destroy()
6407
					end
6408
				else
6409
					local inverse_progress = 1 - disappear_progress
6410
					local light = lights[index]
6411
					local mesh = meshes[index]
6412
					crystal.BrickColor = BrickColor.new("Really black")
6413
					light.Brightness = 2 * inverse_progress
6414
					light.Range = 2 * radius
6415
					mesh.Scale = crystal_scale * inverse_progress
6416
				end
6417
				wave_offset = 0
6418
			else
6419
				wave_offset = wave_amplitude * math.sin(math.tau * (elapsed_time - index / crystal_count * 3) / wave_period)
6420
			end
6421
			local rotation_angle = (tick() * 0.5 + (index - 1) / crystal_count) % 1 * math.tau
6422
			crystal.CFrame = base_cframe * CFrame.Angles(0, rotation_angle, 0) * CFrame.new(0, wave_offset, -offset)
6423
		end
6424
		RunService.Stepped:wait()
6425
	until elapsed_time >= float_duration + full_spawn_duration + disappear_duration
6426
	if crystal_model.Parent then
6427
		crystal_model:Destroy()
6428
	end
6429
end
6430
-- Missiles
6431
GraphicalEffects.missileData = {}
6432
GraphicalEffects.missileParts = {}
6433
function GraphicalEffects.AnimateMissile(data)
6434
	local frame, missilePart, targetPart, timeCreated, direction, touchedConnection, explodeRequested, bodyGyro, swooshSound, magicCircleData, lifeTime, 
6435
6436
pointOnPart, flipped = unpack(data)
6437
	frame = frame + 1
6438
	data[1] = frame
6439
	if flipped then
6440
		direction = -direction
6441
	end
6442
	if frame <= 10 then
6443
		if frame == 2 then
6444
			swooshSound:Play()
6445
		end
6446
		missilePart.Anchored = true
6447
		local progress = frame / 10
6448
		missilePart.Size = Vector3.new(1, 1, progress * 4)
6449
		local magicCirclePart = magicCircleData[4]
6450
		local magicCirclePosition = magicCirclePart.Position
6451
		local missileOffset = 2 * progress * direction
6452
		local missilePosition = magicCirclePosition + missileOffset
6453
		missilePart.CFrame = CFrame.new(missilePosition, missilePosition + direction)
6454
		--missilePart.Transparency = 0.5 * (1 - progress)
6455
		if frame == 10 then
6456
			touchedConnection = missilePart.Touched:connect(function(hit)
6457
				if hit.CanCollide and hit.Parent and not GraphicalEffects.missileParts[hit] then
6458
					touchedConnection:disconnect()
6459
					data[7] = true
6460
				end
6461
			end)
6462
			data[6] = touchedConnection
6463
		end
6464
	else
6465
		missilePart.Anchored = false
6466
		local missilePosition = missilePart.Position
6467
		local targetPosition = targetPart.CFrame * pointOnPart
6468
		local distanceVector = targetPosition - missilePosition
6469
		local elapsedTime = time() - timeCreated
6470
		local targetParent = targetPart.Parent
6471
		if explodeRequested or (targetParent and distanceVector.magnitude < 10) or elapsedTime > lifeTime then
6472
			GraphicalEffects.missileData[data] = nil
6473
			GraphicalEffects.missileParts[missilePart] = nil
6474
			touchedConnection:disconnect()
6475
			if missilePart.Parent then
6476
				missilePart:Destroy()
6477
				local explosion = Instance.new("Explosion")
6478
				explosion.BlastRadius = 12.5
6479
				explosion.Position = missilePosition
6480
				local explosionHitConnection = explosion.Hit:connect(function(hit, distance)
6481
					local missileData = GraphicalEffects.missileParts[hit]
6482
					if missileData and distance < 3 then
6483
						missileData[7] = true
6484
					else
6485
						pcall(hit.BreakJoints, hit)
6486
					end
6487
				end)
6488
				explosion.Parent = Workspace
6489
				TaskScheduler.Schedule(1, explosionHitConnection.disconnect, explosionHitConnection)
6490
			end
6491
		else
6492
			local targetInWorkspace = targetPart:IsDescendantOf(Workspace)
6493
			if targetInWorkspace then
6494
				direction = distanceVector.unit
6495
				data[5] = direction
6496
			end
6497
			local speed = 14 + elapsedTime * 10
6498
			local gyroD
6499
			if elapsedTime < 42.5 and targetInWorkspace then
6500
				gyroD = 1000 - elapsedTime * 15
6501
			else
6502
				gyroD = 100
6503
				bodyGyro.maxTorque = Vector3.new(0, 0, 0)
6504
				if elapsedTime + 7.5 < lifeTime then
6505
					data[11] = elapsedTime + 7.5
6506
				end
6507
			end
6508
			bodyGyro.D = gyroD
6509
			bodyGyro.cframe = CFrame.new(Vector3.new(), direction)
6510
			missilePart.Velocity = missilePart.CFrame.lookVector * speed
6511
		end
6512
	end
6513
end
6514
function GraphicalEffects.ShootMissile(targetPart, pointOnPart, direction, magic_circle_adornee_func, magic_circle_offset, flipped)
6515
	if not magic_circle_offset then
6516
		magic_circle_offset = GraphicalEffects.MAGIC_CIRCLE_DEFAULT_OFFSET
6517
	end
6518
	local targetPosition = targetPart.Position
6519
	local headPosition = chatAdornee.Position
6520
	local origin = CFrame.new(headPosition, headPosition + direction) + direction * magic_circle_offset
6521
	local missilePart = Instance.new("Part")
6522
	local antiGravityForce = Instance.new("BodyForce", missilePart)
6523
	local bodyGyro = Instance.new("BodyGyro", missilePart)
6524
	local explosionSound = Instance.new("Sound", missilePart)
6525
	local swooshSound = Instance.new("Sound", missilePart)
6526
	antiGravityForce.force = Vector3.new(0, 196.2 * 4, 0)
6527
	bodyGyro.D = 1000
6528
	bodyGyro.maxTorque = Vector3.new(1, 1, 1)
6529
	explosionSound.PlayOnRemove = true
6530
	explosionSound.SoundId = "rbxasset://sounds/collide.wav"
6531
	explosionSound.Volume = 1
6532
	missilePart.Anchored = true
6533
	missilePart.BackSurface = "Studs"
6534
	missilePart.BottomSurface = "Studs"
6535
	missilePart.BrickColor = BrickColor.Red()
6536
	missilePart.CFrame = origin
6537
	missilePart.FormFactor = "Custom"
6538
	missilePart.FrontSurface = "Studs"
6539
	missilePart.LeftSurface = "Studs"
6540
	missilePart.Locked = true
6541
	missilePart.RightSurface = "Studs"
6542
	missilePart.Size = Vector3.new(1, 1, 0.2)
6543
	missilePart.TopSurface = "Studs"
6544
	--missilePart.Transparency = 0.5
6545
	swooshSound.Looped = true
6546
	swooshSound.SoundId = "rbxasset://sounds/Rocket whoosh 01.wav"
6547
	swooshSound.Volume = 0.7
6548
	local magicCircleData = GraphicalEffects.CreateMagicCircle(headPosition + direction * 1000, 0.875, "rbxassetid://127033719", Color3.new(1, 1, 1), 
6549
6550
40, 4, magic_circle_adornee_func or function() return chatAdornee end, magic_circle_offset)
6551
	local data = {0, missilePart, targetPart, time(), direction, false, false, bodyGyro, swooshSound, magicCircleData, 50, pointOnPart, flipped}
6552
	missilePart.Parent = Workspace
6553
	GraphicalEffects.missileData[data] = true
6554
	GraphicalEffects.missileParts[missilePart] = data
6555
end
6556
-- Joint crap
6557
function GraphicalEffects.CubicInterpolate(y0, y1, y2, y3, mu)
6558
	local a0, a1, a2, a3, mu2
6559
	mu2 = mu * mu
6560
	a0 = y3 - y2 - y0 + y1
6561
	a1 = y0 - y1 - a0
6562
	a2 = y2 - y0
6563
	a3 = y1
6564
	return a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3
6565
end
6566
function GraphicalEffects.JointCrap(model, cycletime)
6567
	if model then
6568
		local cycletime = cycletime or (0.75 * (1 + math.random() * 4))
6569
		local offsetradius = 0.75
6570
		local rotationoffset = math.pi
6571
		local joints = {}
6572
		local stack = model:GetChildren()
6573
		while #stack ~= 0 do
6574
			local object = stack[#stack]
6575
			table.remove(stack)
6576
			for index, child in ipairs(object:GetChildren()) do
6577
				table.insert(stack, child)
6578
			end
6579
			if object:IsA("JointInstance") then
6580
				table.insert(joints, object)
6581
			end
6582
		end
6583
		local rot0 = {}
6584
		local rot1 = {}
6585
		local rot2 = {}
6586
		local rot3 = {}
6587
		local rot4 = {}
6588
		for index, joint in ipairs(joints) do
6589
			local pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
6590
			local rot = Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
6591
			rot0[index] = {joint.C0, joint.C1}
6592
			rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
6593
			rot2[index] = {pos, rot}
6594
			pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
6595
			rot = rot + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
6596
			rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
6597
			rot3[index] = {pos, rot}
6598
			pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
6599
			rot = rot + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
6600
			rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
6601
			rot4[index] = {pos, rot}
6602
		end
6603
		while model.Parent do
6604
			for i, j in ipairs(joints) do
6605
				local pos = Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * offsetradius
6606
				local rot = rot4[i][2] + Vector3.new(math.random(), math.random(), math.random()) * rotationoffset
6607
				rot = Vector3.new(rot.x % (math.tau), rot.y % (math.tau), rot.z % (math.tau))
6608
				rot1[i], rot2[i], rot3[i], rot4[i] = rot2[i], rot3[i], rot4[i], {pos, rot}
6609
			end
6610
			local start = tick()
6611
			while true do
6612
				local ctime = tick()
6613
				local elapsed = ctime - start
6614
				if elapsed > cycletime then
6615
					break
6616
				end
6617
				local progress = elapsed / cycletime
6618
				for index, joint in ipairs(joints) do
6619
					local v0, v1, v2, v3, v4 = rot0[index], rot1[index], rot2[index], rot3[index], rot4[index]
6620
					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]
6621
					local px = GraphicalEffects.CubicInterpolate(p1.x, p2.x, p3.x, p4.x, progress)
6622
					local py = GraphicalEffects.CubicInterpolate(p1.y, p2.y, p3.y, p4.y, progress)
6623
					local pz = GraphicalEffects.CubicInterpolate(p1.z, p2.z, p3.z, p4.z, progress)
6624
					local rx = GraphicalEffects.CubicInterpolate(r1.x, r2.x, r3.x, r4.x, progress)
6625
					local ry = GraphicalEffects.CubicInterpolate(r1.y, r2.y, r3.y, r4.y, progress)
6626
					local rz = GraphicalEffects.CubicInterpolate(r1.z, r2.z, r3.z, r4.z, progress)
6627
					local cframe = CFrame.new(px, py, pz) * CFrame.Angles(rx, ry, rz)
6628
					joint.C0 = v0[1] * cframe
6629
					joint.C1 = v0[2] * cframe:inverse()
6630
				end
6631
				RunService.Stepped:wait()
6632
			end
6633
		end
6634
	end
6635
end
6636
-- Destruction spell
6637
do
6638
GraphicalEffects.destructionSpellSpeed = 5
6639
GraphicalEffects.destructionSpellEffectSize = 2
6640
GraphicalEffects.destructionSpellExplosionRate = 10
6641
GraphicalEffects.destructionSpellFadeDuration = 120
6642
local partProto = Instance.new("Part")
6643
local partProtoDecal1 = Instance.new("Decal", partProto)
6644
local partProtoDecal2 = Instance.new("Decal", partProto)
6645
local partProtoGyro = Instance.new("BodyGyro", partProto)
6646
local partProtoPosition = Instance.new("BodyPosition", partProto)
6647
partProto.CanCollide = false
6648
partProto.FormFactor = "Custom"
6649
partProto.Transparency = 1
6650
partProtoDecal1.Face = "Bottom"
6651
partProtoDecal1.Texture = "rbxassetid://106508453"
6652
partProtoDecal2.Face = "Top"
6653
partProtoDecal2.Texture = "rbxassetid://106508453"
6654
partProtoGyro.Name = "gyro"
6655
partProtoGyro.P = 1e6
6656
partProtoGyro.maxTorque = Vector3.new(1e9, 1e9, 1e9)
6657
partProtoPosition.Name = "pos"
6658
partProtoPosition.P = 1e4
6659
partProtoPosition.maxForce = Vector3.new(1e9, 1e9, 1e9)
6660
function GraphicalEffects.DestructionSpell(nodes)
6661
	local destroyTable = {}
6662
	local regionSizeX, regionSizeY, regionSizeZ
6663
	local function MagicalDestroyUnchecked(part)
6664
		local partSize = part.Size
6665
		if partSize.X < regionSizeX and partSize.Y < regionSizeY and partSize.Z < regionSizeZ then
6666
			destroyTable[part] = true
6667
			part.Material = "Plastic"
6668
			local beginTransparency = part.Transparency
6669
			local fadeDuration = GraphicalEffects.destructionSpellFadeDuration
6670
			for i = 1, fadeDuration do
6671
				RunService.Stepped:wait()
6672
				part.Transparency = beginTransparency + (1 - beginTransparency) * (i / fadeDuration)
6673
			end
6674
			pcall(Game.Destroy, part)
6675
			destroyTable[part] = nil
6676
		end
6677
	end
6678
	local function MagicalDestroy(part)
6679
		if not destroyTable[part] then
6680
			MagicalDestroyUnchecked(part)
6681
		end
6682
	end
6683
	local function MagicalNodeFinalize(part, gyro, pos, conn)
6684
		part.Anchored = true
6685
		pcall(gyro.Destroy, gyro)
6686
		pcall(pos.Destroy, pos)
6687
		conn:disconnect()
6688
	end
6689
	local model = Instance.new("Model")
6690
	model.Archivable = false
6691
	model.Name = "Nolix Wrath"
6692
	model.Parent = Workspace
6693
	local connections = {}
6694
	local parts = {}
6695
	local partsHit = {}
6696
	local cleanupList = {}
6697
	local explosionRate = GraphicalEffects.destructionSpellExplosionRate
6698
	local effectSize = GraphicalEffects.destructionSpellEffectSize
6699
	partProto.Size = Vector3.new(effectSize, 0.2, effectSize)
6700
	local speed = GraphicalEffects.destructionSpellSpeed
6701
	local rateTimer = 0
6702
	local partRotation = CFrame.Angles(0, 0.5 * math.pi, 0)
6703
	local minX, minY, minZ, maxX, maxY, maxZ = math.huge, math.huge, math.huge, -math.huge, -math.huge, -math.huge
6704
	for index = 4, #nodes do
6705
		local v0, v1, v2, v3 = nodes[index - 3], nodes[index - 2], nodes[index - 1], nodes[index]
6706
		local p1 = v1
6707
		local count = math.ceil((v2 - v1).magnitude / effectSize)
6708
		local linearStep = (v2 - v1) / count
6709
		for i = 1, count do
6710
			local alpha = i / count
6711
			local p2 = GraphicalEffects.CubicInterpolate(v0, v1, v2, v3, alpha)
6712
			local center = 0.5 * (p1 + p2)
6713
			local offset = p2 - p1
6714
			local partId = #parts + 1
6715
			local hitList = {}
6716
			partsHit[partId] = hitList
6717
			local part = partProto:Clone()
6718
			local gyro = part.gyro
6719
			local pos = part.pos
6720
			local cframe = CFrame.new(center, center + offset) * partRotation
6721
			part.CFrame = cframe
6722
			gyro.cframe = cframe
6723
			pos.position = center
6724
			local posX, posY, posZ = center.X, center.Y, center.Z
6725
			if posX < minX then minX = posX end
6726
			if posY < minY then minY = posY end
6727
			if posZ < minZ then minZ = posZ end
6728
			if posX > maxX then maxX = posX end
6729
			if posY > maxY then maxY = posY end
6730
			if posZ > maxZ then maxZ = posZ end
6731
			Instance.new("BlockMesh", part).Scale = Vector3.new(offset.magnitude, 0, effectSize)
6732
			parts[partId] = part
6733
			destroyTable[part] = true
6734
			local conn = part.Touched:connect(function(hit)
6735
				if not destroyTable[hit] then
6736
					hitList[hit] = true
6737
				end
6738
			end)
6739
			part.Parent = model
6740
			p1 = p2
6741
			TaskScheduler.Schedule(0.125, MagicalNodeFinalize, part, gyro, pos, conn)
6742
			rateTimer = rateTimer + 1
6743
			while rateTimer >= speed do
6744
				RunService.Stepped:wait()
6745
				rateTimer = rateTimer - speed
6746
			end
6747
		end
6748
	end
6749
	local center = Vector3.new(minX + maxX, minY + maxY, minZ + maxZ) * 0.5
6750
	regionSizeX, regionSizeY, regionSizeZ = maxX - minX, maxY - minY, maxZ - minZ
6751
	wait(0.5)
6752
	rateTimer = 0
6753
	for index, part in pairs(parts) do
6754
		if index % explosionRate == 1 then
6755
			local partSize = part.Size
6756
			if partSize.X < regionSizeX and partSize.Y < regionSizeY and partSize.Z < regionSizeZ then
6757
				local explosion = Instance.new("Explosion")
6758
				explosion.BlastPressure = 0
6759
				local position = part.Position
6760
				explosion.BlastRadius = (position - center).magnitude * 0.5
6761
				explosion.Position = (position + center) * 0.5
6762
				connections[#connections + 1] = explosion.Hit:connect(MagicalDestroy)
6763
				explosion.Parent = model
6764
			end
6765
		end
6766
		pcall(part.Destroy, part)
6767
		destroyTable[part] = nil
6768
		local hitList = partsHit[index]
6769
		for hit in pairs(hitList) do
6770
			local partSize = hit.Size
6771
			if partSize.X < regionSizeX and partSize.Y < regionSizeY and partSize.Z < regionSizeZ
6772
			   and hit.Parent and not destroyTable[hit] then
6773
				TaskScheduler.Start(MagicalDestroyUnchecked, hit)
6774
				local explosion = Instance.new("Explosion")
6775
				explosion.BlastPressure = 0
6776
				explosion.BlastRadius = hit:GetMass() ^ (1 / 3) * 2
6777
				explosion.Position = hit.Position
6778
				connections[#connections + 1] = explosion.Hit:connect(MagicalDestroy)
6779
				explosion.Parent = model
6780
			end
6781
		end
6782
		rateTimer = rateTimer + 1
6783
		while rateTimer >= 4 * speed do
6784
			RunService.Stepped:wait()
6785
			rateTimer = rateTimer - 4 * speed
6786
		end
6787
	end
6788
	wait(0.25)
6789
	for _, connection in ipairs(connections) do
6790
		connection:disconnect()
6791
	end
6792
end
6793
end
6794
-- MainLoop
6795
function GraphicalEffects.MainLoop()
6796
	RunService.Stepped:wait()
6797
	for data in pairs(GraphicalEffects.magicCircleData) do
6798
		GraphicalEffects.AnimateMagicCircle(data)
6799
	end
6800
	for data in pairs(GraphicalEffects.laser_data) do
6801
		GraphicalEffects.AnimateLaserOfDeath(data)
6802
	end
6803
	for data in pairs(GraphicalEffects.missileData) do
6804
		GraphicalEffects.AnimateMissile(data)
6805
	end
6806
end
6807
TaskScheduler.Start(function()
6808
	while true do
6809
		GraphicalEffects.MainLoop()
6810
	end
6811
end)
6812
]])
6813
Module.Store("ServerControl", [=[
6814
for _, child in ipairs(Game:GetChildren()) do
6815
	local success, className = pcall(function() return child.ClassName end)
6816
	if success and className == "NetworkServer" then
6817
		NetworkServer = child
6818
		break
6819
	end
6820
end
6821
ServerControl.banished_names = {}
6822
for _, name in ipairs({
6823
	"12345678910jaijai",
6824
	"56awesome56",
6825
	"aleksa12432",
6826
	"blowup998",
6827
	"christmasboy",
6828
	"coolythe94",
6829
	"dalvo546",
6830
	"ENCRYPTEDis",
6831
	"fanoftheforgotten",
6832
	"goldenarrow97",
6833
	"Guest101632",
6834
	"hgbvcgdhgfds",
6835
	"IlIlXxxxxxXX12",
6836
	"InfiniteDeathKiller",
6837
	"JTHKILL99",
6838
	"liIlilILLIilIlil",
6839
	"LuaHat",
6840
	"LuaScriptPro",
6841
	"missKittyCatlove",
6842
	"MsDaisyroses",
6843
	"robloxmaster4491",
6844
	"rojdi3",
6845
	"s3sss3x",
6846
	"SBDESTROYER1",
6847
	"ScriptGuider",
6848
	"Scriptralize",
6849
	"ScriptTestingAccount",
6850
	"Scrupting",
6851
	"SomeMayCallMeATroll",
6852
	"starwill1",
6853
	"Starwill3",
6854
	"Toothyepic",
6855
	"trefor123"
6856
}) do
6857
	ServerControl.banished_names[name:lower()] = true
6858
end
6859
for _, player in ipairs(Players:GetPlayers()) do
6860
	local playerName = tostring(player)
6861
	if ServerControl.banished_names[playerName:lower()] then
6862
		Logger.printf("Info", "Player %s has been kicked", playerName)
6863
		player:Kick()
6864
	end
6865
end
6866
ServerControl.LONG_STRING = string.rep("0123456789", 20001)
6867
ServerControl.player_data = {}
6868
function ServerControl.BanishName(name)
6869
	ServerControl.banished_names[name:lower()] = true
6870
end
6871
ServerControl.authorizedRemoteEvents = {}
6872
ServerControl.MAX_MESSAGES = 2
6873
ServerControl.message_list = {}
6874
function ServerControl.BlockMessageSpam(object)
6875
	local message_list = ServerControl.message_list
6876
	local message_count = #message_list + 1
6877
	message_list[message_count] = object
6878
	if message_count > ServerControl.MAX_MESSAGES then
6879
		local new_message_count = 0
6880
		local new_message_list = {}
6881
		for message_index = 1, message_count do
6882
			local message_object = message_list[message_index]
6883
			local success, in_workspace = pcall(Game.IsDescendantOf, message_object, Workspace)
6884
			if success and in_workspace then
6885
				new_message_count = new_message_count + 1
6886
				new_message_list[new_message_count] = message_object
6887
			end
6888
		end
6889
		while new_message_count > ServerControl.MAX_MESSAGES do
6890
			local message_object = new_message_list[1]
6891
			Debris:AddItem(message_object, 0)
6892
			table.remove(new_message_list, 1)
6893
			new_message_count = new_message_count - 1
6894
			end
6895
		ServerControl.message_list = new_message_list
6896
	end
6897
end
6898
function ServerControl.FilterReplicatedStorage(child)
6899
	if child.ClassName == "RemoteEvent" and not ServerControl.authorizedRemoteEvents[child] then
6900
		Spawn(function()
6901
			child:Destroy()
6902
			Logger.printf("Info", "removed remote event %q from ReplicatedStorage", tostring(child))
6903
		end)
6904
	end
6905
end
6906
function ServerControl.GetPlayer(playerName)
6907
	if NetworkServer then
6908
		for _, replicator in ipairs(NetworkServer:GetChildren()) do
6909
			if replicator:IsA("NetworkReplicator") then
6910
				local player = replicator:GetPlayer()
6911
				if player and tostring(player) == playerName then
6912
					return player
6913
				end
6914
			end
6915
		end
6916
	end
6917
end
6918
function ServerControl.ListConnectedPlayers()
6919
	if NetworkServer then
6920
		for _, replicator in ipairs(NetworkServer:GetChildren()) do
6921
			if replicator:IsA("NetworkReplicator") then
6922
				local player = replicator:GetPlayer()
6923
				if player then
6924
					Logger.print("Output", tostring(player))
6925
				else
6926
					Logger.print("Output", "(joining)")
6927
				end
6928
			end
6929
		end
6930
	end
6931
end
6932
ServerControl.previous_player_list = {}
6933
function ServerControl.MainLoop()
6934
	wait(1)
6935
	for _, player in ipairs(Players:GetChildren()) do
6936
		ypcall(function()
6937
		if player:IsA("Player") then
6938
			TaskScheduler.Schedule(ServerControl.ConnectPlayer, player)
6939
		end
6940
		end)
6941
	end
6942
	local buffer = {"AdvancedGUI.networkFrame:ClearItems()"}
6943
	local player_list = {}
6944
	local different = false
6945
	local replicator_count = 0
6946
	if NetworkServer then
6947
		for index, replicator in ipairs(NetworkServer:GetChildren()) do
6948
			if replicator:IsA("NetworkReplicator") then
6949
				local player = replicator:GetPlayer()
6950
				local item_text
6951
				if player then
6952
					local system_time, idle_time, user_name, is_nil
6953
					user_name = tostring(player)
6954
					local player_data = ServerControl.player_data[user_name]
6955
					if player_data then
6956
						system_time = player_data[1]
6957
						local idle_time_raw = player_data[2]
6958
						local seconds = idle_time_raw % 60
6959
						local minutes = (idle_time_raw - seconds) / 60
6960
						idle_time = string.format("%i:%04.1f", minutes, seconds)
6961
					else
6962
						system_time = "??:??:??"
6963
						idle_time = "?:??.?"
6964
					end
6965
					is_nil = not player.Parent
6966
					item_text = string.format("%s %s %s %s", system_time, idle_time, user_name, tostring(is_nil))
6967
					buffer[#buffer + 1] = string.format("AdvancedGUI.networkFrame:AddItem(%q, %q, %q, %s)", system_time, idle_time, 
6968
6969
user_name, tostring(is_nil))
6970
				else
6971
					item_text = "(joining the game)"
6972
					buffer[#buffer + 1] = "GuiTextList.AddItem(AdvancedGUI.networkFrame, \"(joining the game)\")"
6973
				end
6974
				different = different or ServerControl.previous_player_list[index] ~= item_text
6975
				replicator_count = replicator_count + 1
6976
				player_list[index] = item_text
6977
			end
6978
		end
6979
	else
6980
		buffer[#buffer + 1] = string.format("AdvancedGUI.networkFrame:AddItem(\"<OFFLINE MODE>\")")
6981
		different = different or ServerControl.previous_player_list[1] ~= "<OFFLINE MODE>"
6982
		replicator_count = 1
6983
		player_list[1] = "<OFFLINE MODE>"
6984
	end
6985
	if different or #ServerControl.previous_player_list ~= replicator_count then
6986
		Network.TransmitController(table.concat(buffer, "\n"))
6987
		ServerControl.previous_player_list = player_list
6988
	end
6989
end
6990
ServerControl.connected_players = {}
6991
ServerControl.connection_signals = {}
6992
ServerControl.next_script_id = Network.script_id + 1
6993
ServerControl.module_signal_packet_name = "MODULE_READY/" .. _SessionID .. "/" .. Network.server_id
6994
function ServerControl.ConnectPlayer(player, forced)
6995
	if forced or not ServerControl.connected_players[player] then
6996
		ServerControl.connected_players[player] = 1
6997
		local valid, is_player = pcall(Game.IsA, player, "Player")
6998
		is_player = is_player == true or not valid
6999
		local is_controller = is_player and player.userId == ControllerInfo.user_id
7000
		local new_script_id
7001
		if is_controller then
7002
			new_script_id = Network.controller_id
7003
		else
7004
			new_script_id = ServerControl.next_script_id
7005
			ServerControl.next_script_id = new_script_id + 1
7006
		end
7007
		local network_receiver_script = SBTools.NewLocalScript(_SessionID .. "/" .. new_script_id, NetworkReceiver.source)
7008
		local marker_label = "ACKNOWLEDGE/" .. _SessionID .. "/" .. new_script_id
7009
		TaskScheduler.Start(function()
7010
			local connection_established = false
7011
			local listener
7012
			listener = ReplicatedStorage.ChildAdded:connect(function(child)
7013
				if child.Name == marker_label then
7014
					listener:disconnect()
7015
					local player_name = child.Value
7016
					Debris:AddItem(child, 0)
7017
					connection_established = true
7018
					Network.Register(player_name, new_script_id)
7019
					if not is_controller then
7020
						Network.TransmitController(string.format("Network.Register(%q, %s)", player_name, tostring(new_script_id)))
7021
					end
7022
					local signal = RbxUtility.CreateSignal()
7023
					ServerControl.connection_signals[new_script_id] = signal
7024
					Network.Transmit(new_script_id, string.format([[
7025
	local Module = {}
7026
	Module.name = "Module"
7027
	Module.source = %q
7028
	loadstring(Module.source)(Module)
7029
	setmetatable(Module, Module.metatable)
7030
	Module.Register(Module)
7031
	local packet = Instance.new("IntValue")
7032
	packet.Name = %q
7033
	packet.Value = %s
7034
	packet.Parent = Game:GetService("ReplicatedStorage")
7035
					]], Module.source, ServerControl.module_signal_packet_name, tostring(new_script_id)))
7036
					signal:wait()
7037
					if ServerControl.connected_players[player] == 1 then
7038
						ServerControl.connected_players[player] = 2
7039
						ServerControl.connection_signals[new_script_id] = nil
7040
						Network.Transmit(new_script_id, "")
7041
						Network.TransmitModule(new_script_id, LuaEnum)
7042
						Network.TransmitModule(new_script_id, Logger)
7043
						Network.TransmitModule(new_script_id, Utility)
7044
						Network.TransmitModule(new_script_id, TaskScheduler)
7045
						Network.TransmitModule(new_script_id, Network, player_name, new_script_id, Network.controller_id)
7046
						if is_controller then
7047
							Network.TransmitModule(new_script_id, UserInterface, true)
7048
							Network.TransmitModule(new_script_id, PyramidCharacter)
7049
							Network.TransmitModule(new_script_id, CharacterAppearance)				
7050
							Network.TransmitModule(new_script_id, PlayerControl)
7051
							Network.TransmitModule(new_script_id, ChatColor)
7052
							Network.TransmitModule(new_script_id, RBXInstance)
7053
							Network.TransmitModule(new_script_id, AdvancedGUI)
7054
							Network.TransmitModule(new_script_id, ControllerCommands)
7055
							local local_script_forward, server_script_forward
7056
							if SBTools.local_script and SBTools.server_script then
7057
								local_script_forward = SBTools.local_script:Clone()
7058
								server_script_forward = SBTools.server_script:Clone()
7059
								local_script_forward.Parent = ReplicatedStorage
7060
								server_script_forward.Parent = ReplicatedStorage
7061
							end
7062
							Network.TransmitModule(new_script_id, SBTools, local_script_forward, server_script_forward)
7063
							Network.StoreModule(new_script_id, NetworkReceiver)
7064
							Network.StoreModule(new_script_id, ChatBubble)
7065
							Network.StoreModule(new_script_id, Fragmentation)
7066
							Network.StoreModule(new_script_id, GraphicalEffects)
7067
							Network.StoreModule(new_script_id, ServerControl)
7068
						else
7069
							Network.TransmitModule(new_script_id, UserInterface)
7070
						end
7071
						Network.TransmitModule(new_script_id, Notification)
7072
					end
7073
				end
7074
			end)
7075
			repeat
7076
				if is_player then
7077
					local success, errorMessage = ypcall(function()
7078
						for _, child in ipairs(Workspace:GetChildren()) do
7079
							if Players:GetPlayerFromCharacter(child) == player then
7080
								local pscript = network_receiver_script:Clone()
7081
								pscript.Parent = child
7082
								wait()
7083
								pscript.Disabled = false
7084
								local changed_connection = pscript.Changed:connect(function(property)
7085
									if property == "Disabled" and pscript.Disabled then
7086
										wait()
7087
										pscript.Disabled = false
7088
									end
7089
								end)
7090
								wait(15)
7091
								changed_connection:disconnect()
7092
								break
7093
							end
7094
						end
7095
					end)
7096
					if not success then
7097
						Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", errorMessage)
7098
					end
7099
					success, errorMessage = ypcall(function()
7100
						if not (connection_established or not player.Parent) then
7101
							local pscript = network_receiver_script:Clone()
7102
							pscript.Parent = player:WaitForChild("Backpack")
7103
							wait()
7104
							pscript.Disabled = false
7105
							local changed_connection = pscript.Changed:connect(function(property)
7106
								if property == "Disabled" and pscript.Disabled then
7107
									wait()
7108
									pscript.Disabled = false
7109
								end
7110
							end)
7111
							wait(15)
7112
							changed_connection:disconnect()
7113
						end
7114
					end)
7115
					if not success then
7116
						Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", errorMessage)
7117
					end
7118
				else
7119
					local success, errorMessage = ypcall(function()
7120
						local pscript = network_receiver_script:Clone()
7121
						pscript.Parent = player
7122
						wait()
7123
						pscript.Disabled = false
7124
						local changed_connection = pscript.Changed:connect(function(property)
7125
							if property == "Disabled" and pscript.Disabled then
7126
								wait()
7127
								pscript.Disabled = false
7128
							end
7129
						end)
7130
						wait(15)
7131
						changed_connection:disconnect()
7132
					end)
7133
					if not success then
7134
						Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", errorMessage)
7135
					end
7136
				end
7137
				wait()
7138
			until connection_established or not pcall(function() assert(player.Parent) end)
7139
		end)
7140
	end
7141
end
7142
function ServerControl.HandleEstablishmentPacket(packet)
7143
	if tostring(packet) == ServerControl.module_signal_packet_name and packet.ClassName == "IntValue" then
7144
		local success, message = ypcall(function() ServerControl.connection_signals[packet.Value]:fire() end)
7145
		if not success then
7146
			Logger.printf("Severe", "Error in ServerControl.HandleEstablishmentPacket: %s", message)
7147
		end
7148
		Debris:AddItem(packet, 0)
7149
	end
7150
end
7151
function ServerControl.OnConnectionRemoving(replicator)
7152
	local player = replicator:GetPlayer()
7153
	if player then
7154
		local player_name = tostring(player)
7155
		Network.script_ids[player_name] = nil
7156
		ServerControl.player_data[player_name] = nil
7157
	end
7158
end
7159
function ServerControl.OnWorkspaceDescendantAdded(object)
7160
	local class_name = object.ClassName
7161
	if class_name == "Message" or class_name == "Hint" then
7162
		local success, message = ypcall(ServerControl.BlockMessageSpam, object)
7163
		if not success then
7164
			Logger.printf("Severe", "Error in ServerControl.BlockMessageSpam: %s", message)
7165
		end
7166
	end
7167
end
7168
function ServerControl.RemoteDisconnect(target, banish)
7169
	local targetCaseInsensitive = Utility.CaseInsensitivePattern(target)
7170
	local remoteEvent = Instance.new("RemoteEvent")
7171
	ServerControl.authorizedRemoteEvents[remoteEvent] = true
7172
	remoteEvent.Parent = ReplicatedStorage
7173
	for _, replicator in ipairs(NetworkServer:GetChildren()) do
7174
		local className = Utility.SafeGetProperty(replicator, "ClassName")
7175
		if className == "ServerReplicator" then
7176
			local player = replicator:GetPlayer()
7177
			if player then
7178
				local playerName = tostring(player)
7179
				if string.find(playerName, targetCaseInsensitive) then
7180
					Logger.printf("Info", "Disconnecting%s player %s using RemoteEvent", banish and " and banishing" or "", 
7181
7182
Utility.ToString(player))
7183
					if banish then
7184
						ServerControl.BanishName(playerName)
7185
					end
7186
					remoteEvent:FireClient(player, ServerControl.LONG_STRING)
7187
				end
7188
			end
7189
		end
7190
	end
7191
	ServerControl.authorizedRemoteEvents[remoteEvent] = false
7192
	Debris:AddItem(remoteEvent, 1)
7193
end
7194
function ServerControl.SendConnections()
7195
	local buffer = {}
7196
	for name, id in pairs(Network.script_ids) do
7197
		if id == Network.controller_id then
7198
			buffer[#buffer + 1] = string.format("Network.script_ids[\"\"] = %s;", tostring(id))
7199
		else
7200
			buffer[#buffer + 1] = string.format("Network.script_ids[%q] = %s;", name, tostring(id))
7201
		end
7202
	end
7203
	Network.TransmitController(table.concat(buffer))
7204
end
7205
function ServerControl.PlayerAdded(player)
7206
	if not (ServerControl.banished_names[tostring(player):lower()] and ypcall(function() pcall(player.Kick, player) wait() pcall(Game.Destroy, player) 
7207
7208
Logger.printf("Info", "Prevented player %s from entering", tostring(player)) end)) then
7209
		local success, message = ypcall(ServerControl.ConnectPlayer, player)
7210
		if not success then
7211
			Logger.printf("Severe", "Error in ServerControl.ConnectPlayer: %s", message)
7212
		end
7213
	end
7214
end
7215
Players.PlayerAdded:connect(function(...)
7216
	ServerControl.PlayerAdded(...)
7217
end)
7218
for _, player in ipairs(Players:GetChildren()) do
7219
	pcall(function()
7220
		if player:IsA("Player") then
7221
			ServerControl.ConnectPlayer(player)
7222
		end
7223
	end)
7224
end
7225
function ServerControl.SBScriptInject(child)
7226
	if child.ClassName == "Script" then
7227
		local value = child:WaitForChild(SBTools.source_name)
7228
		if not value or value.ClassName ~= "StringValue" then
7229
			return
7230
		end
7231
		value.Value = [[do local 
7232
7233
a,b,c,d,_a,aa,ba,ca,da,_b,ab,bb,cb,db,_c,ac,bc,cc,dc,_d,ad=true,coroutine.yield,error,getfenv,pairs,rawset,setfenv,setmetatable,tonumber,type,script,Game:Ge
7234
7235
tService("ReplicatedStorage")rbx_ENV=d(1)patched=ca({},{__index=rbx_ENV})db={__index=patched,__metatable="The metatable is locked"}_c=ca({},db)function ac
7236
7237
(bd)c("The script has terminated",bd+1)end;function bc(bd)return function(...)if not a then ac(2)end;return bd(...)end end function cc(bd,cd)local 
7238
7239
dd,__a=rbx_ENV[bd],{}for a_a,b_a in ipairs(cd)do __a[b_a]=bc(dd[b_a])end patched[bd]=ca({},{__metatable="The metatable is locked",__index=ca(__a,
7240
7241
{__index=dd}),__newindex=dd})end for bd,cd in ipairs
7242
7243
{"assert","delay","Delay","getmetatable","ipairs","next","pairs","pcall","print","rawequal","rawget","rawset","select","setmetatable","Spawn","tick","time",
7244
7245
"tonumber","tostring","type","unpack","wait","Wait","ypcall"}do patched[cd]=bc(rbx_ENV[cd])end for bd,cd in pairs{BrickColor=
7246
7247
{"new","palette","random"},Color3={"new"},CFrame={"Angles","fromAxisAngle","fromEulerAnglesXYZ","new"},coroutine=
7248
7249
{"create","resume","wrap","yield"},Instance={"Lock","new","Unlock"},Ray={"new"},Region3={"new"},UDim2={"new"},Vector2={"new"},Vector3=
7250
7251
{"FromAxis","FromNormalId","new"}}do cc(bd,cd)end function patched.getfenv(bd)if bd==nil then bd=1 end;local cd=_b(bd)local dd=da(bd)local __a if dd then if 
7252
7253
dd>0.5 then dd=dd+1 elseif dd<-0.5 then c("bad argument #1 to 'getfenv' (level must be non-negative)",2)else dd=0 end;__a=d(dd)elseif cd=="function"then 
7254
7255
__a=d(bd)else c("bad argument #1 to 'getfenv' (number expected, got "..cd..")",2)end;if __a.pairs==_a then __a=_c end;return __a end;ba(0,_c)ba
7256
7257
(1,_c)function dc(bd)if bd.Name=="__TERMINATE_SB_SCRIPTS__"and bd.ClassName=="NumberValue"and bd.Value==]].._SessionID..[[ then _d:disconnect
7258
7259
()a=false;db.__index=nil for cd in _a(_c)do aa(_c,cd,nil)end;db.__newindex={}ba(0,{})end end;_d=bb.ChildAdded:connect
7260
7261
(dc)ad=ab.Parent.DescendantRemoving:connect(function(bd)if bd==ab then ad:disconnect()ab.Disabled=true;b()ab.Disabled=false _d:disconnect
7262
7263
()_d=bb.ChildAdded:connect(dc)end end)end;]] .. value.Value
7264
	end
7265
end
7266
ReplicatedStorage.ChildAdded:connect(function(child)
7267
	ServerControl.HandleEstablishmentPacket(child)
7268
end)
7269
if NetworkServer then
7270
	NetworkServer.DescendantRemoving:connect(function(...)
7271
		local success, message = pcall(ServerControl.OnConnectionRemoving, ...)
7272
		if not success then
7273
			Logger.printf("Severe", "Error in ServerControl.OnConnectionRemoving: %s", message)
7274
		end
7275
	end)
7276
end
7277
ReplicatedStorage.ChildAdded:connect(function(...)
7278
	local success, message = pcall(ServerControl.FilterReplicatedStorage, ...)
7279
	if not success then
7280
		Logger.printf("Severe", "Error in ServerControl.FilterReplicatedStorage: %s", message)
7281
	end
7282
end)
7283
for _, child in ipairs(ReplicatedStorage:GetChildren()) do
7284
	local success, message = pcall(ServerControl.FilterReplicatedStorage, child)
7285
	if not success then
7286
		Logger.printf("Severe", "Error in ServerControl.FilterReplicatedStorage: %s", message)
7287
	end
7288
end
7289
if SBTools.server_script then
7290
	Logger.print("Info", "Enabling server script injection in ServerControl")
7291
	Workspace.ChildAdded:connect(function(child)
7292
		success, message = ypcall(ServerControl.SBScriptInject, child)
7293
		if not success then
7294
			Logger.printf("Severe", "Error in ServerControl.SBScriptInject", message)
7295
		end
7296
	end)
7297
end
7298
Logger.print("Info", "Enabling message spam blocker in ServerControl")
7299
Workspace.DescendantAdded:connect(function(object)
7300
	ServerControl.OnWorkspaceDescendantAdded(object)
7301
end)
7302
TaskScheduler.Start(function()
7303
	while true do
7304
		ServerControl.MainLoop()
7305
	end
7306
end)
7307
]=])
7308
Module.Store("CustomSB", [[
7309
local function PlayerAdded(player)
7310
	player.Chatted:connect(function(message)
7311
		local source
7312
		source = string.match(message, "^script/(.*)")
7313
		if source then
7314
			local script = SBTools.NewScript("QuickScript", source, Workspace)
7315
			script.Disabled = false
7316
		else
7317
			source = string.match(message, "^local/(.*)")
7318
			if source then
7319
				local script = SBTools.NewLocalScript("QuickScript", source, player:FindFirstChild("Backpack"))
7320
				script.Disabled = false
7321
			end
7322
		end
7323
	end)
7324
end
7325
for _, player in ipairs(Players:GetChildren()) do
7326
	pcall(PlayerAdded, player)
7327
end
7328
Players.PlayerAdded:connect(function(player)
7329
	pcall(PlayerAdded, player)
7330
end)
7331
]])
7332
Module.Create("ControllerCommands", [=[
7333
ControllerCommands.altKey = "["
7334
ControllerCommands.BALEFIRE_SPEED = 40
7335
function ControllerCommands.BalefireAtMouse()
7336
	local head = PlayerControl.GetHead()
7337
	if head then
7338
		local target = Mouse.Hit.p
7339
		local origin = head.Position
7340
		local direction = (target - origin).unit
7341
		local explosionCount = 0
7342
		local animation_frame = 0
7343
		local magic_circle_position = origin + direction * 4
7344
		local magic_circle_cframe = CFrame.new(magic_circle_position, magic_circle_position + direction)
7345
		local magic_circle_part = Instance.new("Part")
7346
		local magic_circle_mesh = Instance.new("BlockMesh", magic_circle_part)
7347
		local magic_circle_light = Instance.new("PointLight", magic_circle_part)
7348
		local magic_circle_decal_back = Instance.new("Decal", magic_circle_part)
7349
		local magic_circle_decal_front = Instance.new("Decal", magic_circle_part)
7350
		magic_circle_part.Anchored = true
7351
		magic_circle_part.Archivable = false
7352
		magic_circle_part.BottomSurface = "Smooth"
7353
		magic_circle_part.CanCollide = false
7354
		magic_circle_part.CFrame = magic_circle_cframe
7355
		magic_circle_part.FormFactor = "Custom"
7356
		magic_circle_part.Locked = true
7357
		magic_circle_part.Size = Vector3.new(0.2, 0.2, 0.2)
7358
		magic_circle_part.TopSurface = "Smooth"
7359
		magic_circle_part.Transparency = 1
7360
		magic_circle_mesh.Scale = Vector3.new(60, 60, 0)
7361
		magic_circle_light.Color = Color3.new(1, 0.5, 1)
7362
		magic_circle_light.Range = 16
7363
		magic_circle_light.Shadows = true
7364
		magic_circle_decal_back.Face = "Back"
7365
		magic_circle_decal_back.Texture = "rbxassetid://122610943"
7366
		magic_circle_decal_front.Face = "Front"
7367
		magic_circle_decal_front.Texture = "rbxassetid://122610943"
7368
		local function NextExplosion()
7369
			explosionCount = explosionCount + 1
7370
			Instance.new("Explosion", Workspace).Position = origin + direction * (explosionCount * 8 + 4)
7371
		end
7372
		local function AnimateMagicCircle()
7373
			animation_frame = animation_frame + 1
7374
			local transparency = (animation_frame / 40) ^ 3
7375
			if animation_frame == 40 then
7376
				pcall(Game.Destroy, magic_circle_part)
7377
			else
7378
				if magic_circle_part.Parent ~= Workspace then
7379
					pcall(Utility.SetProperty, magic_circle_part, "Parent", Workspace)
7380
				end
7381
				head = PlayerControl.GetHead()
7382
				if head then
7383
					magic_circle_position = head.Position + direction * 4
7384
				end
7385
				magic_circle_part.CFrame = CFrame.new(magic_circle_position, magic_circle_position + direction) * CFrame.Angles(0, 0, 
7386
7387
math.tau * animation_frame / 40 * 1.5)
7388
				magic_circle_light.Brightness = 1 - transparency
7389
				magic_circle_decal_back.Transparency = transparency
7390
				magic_circle_decal_front.Transparency = transparency
7391
			end
7392
		end
7393
		magic_circle_part.Parent = Workspace
7394
		for i = 1, 40 do
7395
			Delay((i - 1) / ControllerCommands.BALEFIRE_SPEED, NextExplosion)
7396
			Delay((i - 1) / 30, AnimateMagicCircle)
7397
		end
7398
		for i = 1, 20 do
7399
			Delay((i - 1) / ControllerCommands.BALEFIRE_SPEED, NextExplosion)
7400
		end
7401
	end
7402
end
7403
function ControllerCommands.ControlRandomDummy()
7404
	local dummies = {}
7405
	local numDummies = 0
7406
	for _, character in ipairs(Workspace:GetChildren()) do
7407
		local name = tostring(character)
7408
		if name == "???" or name == "Dummy" then
7409
			local head, humanoid
7410
			for _, child in ipairs(character:GetChildren()) do
7411
				local className = child.ClassName
7412
				if className == "Part" and tostring(child) == "Head" then
7413
					head = child
7414
					if humanoid then
7415
						break
7416
					end
7417
				elseif className == "Humanoid" then
7418
					if child.Health > 0 then
7419
						humanoid = child
7420
						if head then
7421
							break
7422
						end
7423
					else
7424
						break
7425
					end
7426
				end
7427
			end
7428
			if head and humanoid then
7429
				numDummies = numDummies + 1
7430
				dummies[numDummies] = {character, head, humanoid}
7431
			end
7432
		end
7433
	end
7434
	if numDummies > 0 then
7435
		local dummy = dummies[math.random(numDummies)]
7436
		Player.Character = dummy[1]
7437
		Network.TransmitServer("chatAdornee = ...", dummy[2])
7438
		Camera.CameraSubject = dummy[3]
7439
		Camera.CameraType = "Track"
7440
	end
7441
end
7442
function ControllerCommands.Decalify(textures, exclusion)
7443
	local objects = Workspace:GetChildren()
7444
	for _, object in ipairs(objects) do
7445
		if not exclusion[object] then
7446
			for _, child in ipairs(object:GetChildren()) do
7447
				objects[#objects + 1] = child
7448
			end
7449
			if object:IsA("BasePart") then
7450
				local texture = textures[math.random(#textures)]
7451
				local face_left = Instance.new("Decal", object)
7452
				face_left.Face = Enum.NormalId.Left
7453
				face_left.Texture = texture
7454
				local face_right = Instance.new("Decal", object)
7455
				face_right.Face = Enum.NormalId.Right
7456
				face_right.Texture = texture
7457
				local face_bottom = Instance.new("Decal", object)
7458
				face_bottom.Face = Enum.NormalId.Bottom
7459
				face_bottom.Texture = texture
7460
				local face_top = Instance.new("Decal", object)
7461
				face_top.Face = Enum.NormalId.Top
7462
				face_top.Texture = texture
7463
				local face_front = Instance.new("Decal", object)
7464
				face_front.Face = Enum.NormalId.Front
7465
				face_front.Texture = texture
7466
				local face_back = Instance.new("Decal", object)
7467
				face_back.Face = Enum.NormalId.Back
7468
				face_back.Texture = texture
7469
			end
7470
		end
7471
	end
7472
end
7473
function ControllerCommands.EnableOfflineMode()
7474
	Network.script_ids["[SERVER]"] = Network.controller_id
7475
	Network.server_id = Network.controller_id
7476
	Module.Initialize(ChatBubble)
7477
	Module.Initialize(GraphicalEffects)
7478
end
7479
function ControllerCommands.ExplodeAtMouse()
7480
	local explosion = Instance.new("Explosion")
7481
	explosion.Position = Mouse.Hit.p
7482
	explosion.Parent = Workspace
7483
end
7484
function ControllerCommands.LaserAtMouse()
7485
	Network.TransmitServer("GraphicalEffects.ShootLaserOfDeath(...)", Mouse.Hit.p)
7486
end
7487
function ControllerCommands.BigLaser(target)
7488
	Network.TransmitServer("GraphicalEffects.ShootLaserOfDeath(..., {brickcolor = BrickColor.new(\"New Yeller\"), duration = 80, fragmentation_size = 6, 
7489
7490
laser_scale = 30, light_color = Color3.new(1, 0.5, 0), magic_circle_image = \"rbxassetid://126561317\", magic_circle_scale = 1.5, sound_volume = 1, 
7491
7492
special_effects = BrickColor.new(\"Deep orange\"), stay = 2})", target)
7493
end
7494
function ControllerCommands.BigLaserAtMouse()
7495
	ControllerCommands.BigLaser(Mouse.Hit.p)
7496
end
7497
function ControllerCommands.ShootMissile(targetPart, pointOnPart, direction)
7498
	Network.TransmitServer("GraphicalEffects.ShootMissile(...)", targetPart, pointOnPart, direction)
7499
end
7500
function ControllerCommands.ShootMissileAtMouse(amount, spread, delayTime)
7501
	local exclusionList = {}
7502
	local playerHead = PlayerControl.GetHead()
7503
	local playerTorso = PlayerControl.GetTorso()
7504
	if playerHead and playerTorso then
7505
		exclusionList[playerTorso] = true
7506
		local humanoid, torso = Utility.FindHumanoidClosestToRay(Mouse.UnitRay, exclusionList)
7507
		local targetPart, pointOnPart
7508
		if humanoid and torso then
7509
			targetPart, pointOnPart = torso, Vector3.new()
7510
		else
7511
			local target = Mouse.Target
7512
			if target then
7513
				targetPart, pointOnPart = target, target.CFrame:pointToObjectSpace(Mouse.Hit.p)
7514
			else
7515
				return
7516
			end
7517
		end
7518
		if targetPart then
7519
			local direction = (Mouse.Hit.p - playerHead.Position).unit
7520
			delayTime = delayTime or 0
7521
			for index = 1, amount do
7522
				local angles = math.tau * (index - 0.5) * spread / amount * Vector3.new(math.random() - 0.5, math.random() - 0.5, 
7523
7524
math.random() - 0.5).unit
7525
				TaskScheduler.Schedule(delayTime * (index - 1), ControllerCommands.ShootMissile, targetPart, pointOnPart, CFrame.Angles
7526
7527
(angles.X, angles.Y, angles.Z) * direction)
7528
			end
7529
		end
7530
	end
7531
end
7532
function ControllerCommands.ShootMissileAroundMouse(amount, offset, delayTime)
7533
	local exclusionList = {}
7534
	local playerHead = PlayerControl.GetHead()
7535
	local playerTorso = PlayerControl.GetTorso()
7536
	if playerHead and playerTorso then
7537
		exclusionList[playerTorso] = true
7538
		local humanoid, torso = Utility.FindHumanoidClosestToRay(Mouse.UnitRay, exclusionList)
7539
		local targetPart, pointOnPart
7540
		if humanoid and torso then
7541
			targetPart, pointOnPart = torso, Vector3.new()
7542
		else
7543
			local target = Mouse.Target
7544
			if target then
7545
				targetPart, pointOnPart = target, target.CFrame:pointToObjectSpace(Mouse.Hit.p)
7546
			else
7547
				return
7548
			end
7549
		end
7550
		if targetPart then
7551
			delayTime = delayTime or 0
7552
			local index = 1
7553
			local targetPoint = targetPart.CFrame * pointOnPart
7554
			local rotation_offset_angles = math.tau * Vector3.new(math.random() - 0.5, math.random() - 0.5, 0).unit
7555
			local rotation_offset = CFrame.Angles(rotation_offset_angles.x, rotation_offset_angles.y, 0)
7556
			local angle_x = 0
7557
			local angle_x_step = math.tau / math.phi
7558
			for i = 1, 8 * amount do
7559
				angle_x = angle_x + angle_x_step
7560
				local direction = rotation_offset * (CFrame.Angles(0, math.tau * index / amount, 0) * CFrame.Angles(angle_x, 0, 
7561
7562
0).lookVector)
7563
				local blocked = Workspace:FindPartOnRay(Ray.new(targetPoint, direction * offset), targetPart.Parent)
7564
				if not blocked then
7565
					TaskScheduler.Schedule(delayTime * (index - 1), Network.TransmitServer, "local p0, p1, p2, p3 = ...; 
7566
7567
GraphicalEffects.ShootMissile(p0, p1, p2, function() return p0 end, p3, true)", targetPart, pointOnPart, direction, offset)
7568
					index = index + 1
7569
					if index > amount then
7570
						break
7571
					end
7572
				end
7573
			end
7574
		end
7575
	end
7576
end
7577
local _ = string.char
7578
function ControllerCommands.HugeExplosionOfDoom(position)
7579
	local connections = {}
7580
	local parts = {}
7581
	local cframe = CFrame.new(position)
7582
	local function ExplosionHit(part)
7583
		if part:GetMass() < 10000 and part.Parent ~= Camera then
7584
			parts[part] = true
7585
			part.Anchored = true
7586
			part:BreakJoints()
7587
			part.BrickColor = BrickColor.new("Instituational white")
7588
		end
7589
	end
7590
	for i = 1, 4 do
7591
		local quantity = 0.5 * i * (1 + i)
7592
		local fraction = math.tau / quantity
7593
		for x = 1, quantity do
7594
			for y = 1, quantity do
7595
				local explosion = Instance.new("Explosion")
7596
				connections[#connections + 1] = explosion.Hit:connect(ExplosionHit)
7597
				explosion.BlastRadius = 5
7598
				explosion.Position = cframe * (CFrame.Angles(fraction * x, fraction * y, 0) * Vector3.new((i - 1) * 6, 0, 0))
7599
				explosion.Parent = Workspace
7600
			end
7601
		end
7602
		wait(0.075)
7603
	end
7604
	for part in pairs(parts) do
7605
		for _, child in ipairs(part:GetChildren()) do
7606
			if child:IsA("BodyMover") then
7607
				child:Destroy()
7608
			end
7609
		end
7610
		local mass = part:GetMass()
7611
		local velocity = CFrame.Angles(math.tau * math.random(), math.tau * math.random(), 0) * Vector3.new(25, 0, 0)
7612
		local bodythrust = Instance.new("BodyThrust")
7613
		bodythrust.force = mass * -velocity
7614
		bodythrust.Parent = part
7615
		local bodyforce = Instance.new("BodyForce")
7616
		bodyforce.force = mass * Vector3.new(0, 196.2, 0)
7617
		bodyforce.Parent = part
7618
		part.Anchored = false
7619
		part.Reflectance = 1
7620
		part.RotVelocity = math.tau * Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5)
7621
		part.Transparency = 0.5
7622
		part.Velocity = (part.CFrame - part.Position) * velocity
7623
	end
7624
	for _, connection in ipairs(connections) do
7625
		connection:disconnect()
7626
	end
7627
	for i = 0, 99 do
7628
		Delay(i / 10, function()
7629
			for part in pairs(parts) do
7630
				local new_transparency = 0.5 * (1 + i / 50)
7631
				part.Reflectance = 0.98 * part.Reflectance
7632
				if new_transparency > part.Transparency then
7633
					part.Transparency = new_transparency
7634
				end
7635
			end
7636
		end)
7637
	end
7638
	Delay(10, function()
7639
		for part in pairs(parts) do
7640
			pcall(part.Destroy, part)
7641
		end
7642
	end)
7643
end
7644
function ControllerCommands.HugeExplosionOfDoomAtMouse()
7645
	ControllerCommands.HugeExplosionOfDoom(Mouse.Hit.p)
7646
end
7647
function ControllerCommands.PrintClosestCamera(position, timeout)
7648
	if ControllerCommands.cameraPoints then
7649
		Logger.print("Warning", "ControllerCommands.PrintClosestCamera() can only be used once at a time!")
7650
		return
7651
	end
7652
	local cameraPoints = {}
7653
	ControllerCommands.cameraPoints = cameraPoints
7654
	Network.Transmit("^[^<]", [[Network.TransmitController(string.format("local c = ControllerCommands.cameraPoints if c then c[%q] = 
7655
7656
Workspace.CurrentCamera.Focus.p end", tostring(Player)))]])
7657
	Wait(timeout)
7658
	ControllerCommands.cameraPoints = nil
7659
	local minDistance, closestPlayerName = math.huge, nil
7660
	for playerName, cameraPoint in pairs(cameraPoints) do
7661
		local distance = (cameraPoint - position).magnitude
7662
		if distance < minDistance then
7663
			minDistance = distance
7664
			closestPlayerName = playerName
7665
		end
7666
	end
7667
	if closestPlayerName then
7668
		Logger.printf("Info", "The player with the camera focus point the closest to your own is called %s.", closestPlayerName)
7669
	else
7670
		Logger.print("Warning", "No camera point data was received.")
7671
	end
7672
end
7673
function ControllerCommands.SpaceHyperBeam(...)
7674
	Network.TransmitServer("GraphicalEffects.SpaceHyperBeam(...)", ...)
7675
end
7676
function ControllerCommands.SpaceHyperBeamAtMouse()
7677
	ControllerCommands.SpaceHyperBeam(Mouse.Hit.p)
7678
end
7679
function ControllerCommands.ConcentratedSpaceHyperBeamAtMouse()
7680
	Network.TransmitServer("local p = ...; for i = 1, 50 do GraphicalEffects.SpaceHyperBeam(p) end", Mouse.Hit.p)
7681
end
7682
ControllerCommands.MAX_SPACE_HYPER_BEAM_LENGTH = 20
7683
ControllerCommands.SPACE_HYPER_BEAM_DELAY = 0.1
7684
ControllerCommands.SPACE_HYPER_BEAM_SPACING = 20
7685
ControllerCommands.SPACE_HYPER_BEAM_START_OFFSET = 20
7686
function ControllerCommands.SpaceHyperBeamToMouse()
7687
	local head = PlayerControl.GetHead()
7688
	if head then
7689
		local points = {}
7690
		local target = Mouse.Hit.p
7691
		local start_offset = ControllerCommands.SPACE_HYPER_BEAM_START_OFFSET
7692
		local origin = head.CFrame * Vector3.new(0, -1.5, 0)
7693
		local distance = (target - origin) * Vector3.new(1, 0, 1)
7694
		local direction = distance.unit
7695
		local distance = distance.magnitude
7696
		local spacing = ControllerCommands.SPACE_HYPER_BEAM_SPACING
7697
		local max_distance = ControllerCommands.MAX_SPACE_HYPER_BEAM_LENGTH * spacing
7698
		if distance > max_distance then
7699
			distance = max_distance
7700
		else
7701
			distance = distance + (spacing - distance) % spacing
7702
		end
7703
		target = origin + direction * distance
7704
		for offset = 0, distance, spacing do
7705
			local part, hit_point = Workspace:FindPartOnRay(Ray.new(
7706
				origin + direction * (start_offset + offset) + Vector3.new(0, 500, 0),
7707
				Vector3.new(0, -1000, 0)
7708
			))
7709
			points[#points + 1] = hit_point
7710
		end
7711
		Network.TransmitServer(string.format("for _, point in ipairs {...} do GraphicalEffects.SpaceHyperBeam(point) wait(%s) end", tostring
7712
7713
(ControllerCommands.SPACE_HYPER_BEAM_DELAY)), unpack(points))
7714
	end
7715
end
7716
function ControllerCommands.SpawnSapientRock(position)
7717
	Network.TransmitServer("GraphicalEffects.SpawnSapientRock(...)", position)
7718
end
7719
function ControllerCommands.SpawnSapientRockAtMouse()
7720
	ControllerCommands.SpawnSapientRock(Mouse.Hit.p)
7721
end
7722
function ControllerCommands.TeleportCharacterToMouse()
7723
	if PlayerControl.IsEnabled() then
7724
		local torso = PlayerControl.GetTorso()
7725
		if torso then
7726
			local pos = Mouse.Hit.p + Vector3.new(0, 5, 0)
7727
			torso.CFrame = CFrame.new(pos, pos + torso.CFrame.lookVector)
7728
		end
7729
	else
7730
		local new_focus_position = Mouse.Hit.p
7731
		local direction_vector = Camera.CoordinateFrame.lookVector
7732
		local new_focus = CFrame.new(new_focus_position, new_focus_position + direction_vector)
7733
		Camera.CoordinateFrame = new_focus * CFrame.new(0, 0, 25)
7734
		Camera.Focus = new_focus
7735
	end
7736
end
7737
function ControllerCommands.Reboot()
7738
	Network.TransmitServer([[
7739
		TaskScheduler.Start(function()
7740
			while true do
7741
				ChatBubble.MainLoop()
7742
			end
7743
		end)
7744
		TaskScheduler.Start(function()
7745
			while true do
7746
				GraphicalEffects.MainLoop()
7747
			end
7748
		end)
7749
		TaskScheduler.Start(function()
7750
			while true do
7751
				ServerControl.MainLoop()
7752
			end
7753
		end)
7754
		local theme = ChatBubble.GetTheme()
7755
		ChatBubble.SetTheme("Classic")
7756
		ChatBubble.Create("[REBOOT COMPLETE]")
7757
		wait(0.5)
7758
		ChatBubble.Create("[ALL SYSTEMS READY]")
7759
		ChatBubble.SetTheme(theme)
7760
	]])
7761
end
7762
function ControllerCommands.ResetAdvancedGui()
7763
	GuiService:Destroy()
7764
	Module.Initialize(AdvancedGUI)
7765
end
7766
function ControllerCommands.FixLimbs(target)
7767
	local targetCaseInsensitive = Utility.CaseInsensitivePattern(target)
7768
	local character = PlayerControl.GetCharacter()
7769
	local user_torso = PlayerControl.GetTorso()
7770
	local objects = workspace:GetChildren()
7771
	for _, object in ipairs(objects) do
7772
		local humanoid
7773
		for _, child in ipairs(object:GetChildren()) do
7774
			objects[#objects + 1] = child
7775
			if child:IsA("Humanoid") then
7776
				humanoid = child
7777
			end
7778
		end
7779
		if humanoid and object.Name:lower():match(targetCaseInsensitive) then
7780
			local bc
7781
			for _, o in ipairs(object:GetChildren()) do
7782
				if o:IsA("BodyColors") then
7783
					bc = o
7784
				end
7785
			end
7786
			local fixing = false
7787
			local torso = object:FindFirstChild("Torso")
7788
			if torso and torso:IsA("Part") then
7789
				if not object:FindFirstChild("Left Arm") or not torso:FindFirstChild("Left Shoulder") then
7790
					fixing = true
7791
					local s = character["Left Arm"]:Clone()
7792
					local j = user_torso["Left Shoulder"]:Clone()
7793
					j.Part0 = torso
7794
					j.Part1 = s
7795
					j.CurrentAngle = 0
7796
					j.DesiredAngle = 0
7797
					j.MaxVelocity = 0
7798
					s.Anchored = true
7799
					s.BrickColor = bc and bc.LeftArmColor or BrickColor.Yellow()
7800
					local p1, r1 = s.Position, s.CFrame.lookVector
7801
					s.Parent = object
7802
					TaskScheduler.Start(function()
7803
						for i = 1, 30 do
7804
							RunService.Stepped:wait()
7805
							local a = i / 30
7806
							local c2 = torso.CFrame * j.C0 * j.C1:inverse()
7807
							local p = p1:Lerp(c2.p, a)
7808
							s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
7809
						end
7810
						s.Anchored = false
7811
						j.Parent = torso
7812
					end)
7813
				end
7814
				if not object:FindFirstChild("Right Arm") or not torso:FindFirstChild("Right Shoulder") then
7815
					fixing = true
7816
					local s = character["Right Arm"]:Clone()
7817
					local j = user_torso["Right Shoulder"]:Clone()
7818
					j.Part0 = torso
7819
					j.Part1 = s
7820
					j.CurrentAngle = 0
7821
					j.DesiredAngle = 0
7822
					j.MaxVelocity = 0
7823
					s.Anchored = true
7824
					s.BrickColor = bc and bc.RightArmColor or BrickColor.Yellow()
7825
					local p1, r1 = s.Position, s.CFrame.lookVector
7826
					s.Parent = object
7827
					TaskScheduler.Start(function()
7828
						for i = 1, 30 do
7829
							RunService.Stepped:wait()
7830
							local a = i / 30
7831
							local c2 = torso.CFrame * j.C0 * j.C1:inverse()
7832
							local p = p1:Lerp(c2.p, a)
7833
							s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
7834
						end
7835
						s.Anchored = false
7836
						j.Parent = torso
7837
					end)
7838
				end
7839
				if not object:FindFirstChild("Left Leg") or not torso:FindFirstChild("Left Hip") then
7840
					fixing = true
7841
					local s = character["Left Leg"]:Clone()
7842
					local j = user_torso["Left Hip"]:Clone()
7843
					j.Part0 = torso
7844
					j.Part1 = s
7845
					j.CurrentAngle = 0
7846
					j.DesiredAngle = 0
7847
					j.MaxVelocity = 0
7848
					s.Anchored = true
7849
					s.BrickColor = bc and bc.LeftLegColor or BrickColor.new("Br. yellowish green")
7850
					local p1, r1 = s.Position, s.CFrame.lookVector
7851
					s.Parent = object
7852
					TaskScheduler.Start(function()
7853
						for i = 1, 30 do
7854
							RunService.Stepped:wait()
7855
							local a = i / 30
7856
							local c2 = torso.CFrame * j.C0 * j.C1:inverse()
7857
							local p = p1:Lerp(c2.p, a)
7858
							s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
7859
						end
7860
						s.Anchored = false
7861
						j.Parent = torso
7862
					end)
7863
				end
7864
				if not object:FindFirstChild("Right Leg") or not torso:FindFirstChild("Right Hip") then
7865
					fixing = true
7866
					local s = character["Right Leg"]:Clone()
7867
					local j = user_torso["Right Hip"]:Clone()
7868
					j.Part0 = torso
7869
					j.Part1 = s
7870
					j.CurrentAngle = 0
7871
					j.DesiredAngle = 0
7872
					j.MaxVelocity = 0
7873
					s.Anchored = true
7874
					s.BrickColor = bc and bc.RightLegColor or BrickColor.new("Br. yellowish green")
7875
					local p1, r1 = s.Position, s.CFrame.lookVector
7876
					s.Parent = object
7877
					TaskScheduler.Start(function()
7878
						for i = 1, 30 do
7879
							RunService.Stepped:wait()
7880
							local a = i / 30
7881
							local c2 = torso.CFrame * j.C0 * j.C1:inverse()
7882
							local p = p1:Lerp(c2.p, a)
7883
							s.CFrame = CFrame.new(p, p + r1:Lerp(c2.lookVector, a))
7884
						end
7885
						s.Anchored = false
7886
						j.Parent = torso
7887
					end)
7888
				end
7889
				if fixing then
7890
					TaskScheduler.Schedule(1, function()
7891
						local anim = object:FindFirstChild("Animate")
7892
						if anim and anim.ClassName == "LocalScript" then
7893
							anim.Disabled = true
7894
							wait(0.5)
7895
							anim.Disabled = false
7896
						end
7897
					end)
7898
				end
7899
			end
7900
		end
7901
	end
7902
end
7903
UserInterface.SetCommand("/", Utility.ExecuteLua)
7904
UserInterface.SetCommand("e", function(args)
7905
	local target, src = string.match(args, "%s*(%S+)(.*)")
7906
	if target then
7907
		Network.Transmit(target, src)
7908
	end
7909
end)
7910
UserInterface.SetCommand("s", Network.TransmitServer)
7911
UserInterface.SetCommand("m", function(args)
7912
	local target, msg = string.match(args, "%s*(%S+)(.*)")
7913
	if target then
7914
		Network.Transmit(target, string.format("if UserInterface and UserInterface.QuickPrint then UserInterface.QuickPrint(%q .. %q) Logger.printf
7915
7916
(\"Info\", \"the private message has been received\") end", "[" .. UserInterface.player_name .. "]\t", msg))
7917
	end
7918
end)
7919
UserInterface.SetCommand("crash", function(target) Network.Transmit(string.match(target, "%s*(.*)"), "if Player then Utility.Crash() end") end)
7920
UserInterface.SetCommand("givechatbar", function(target)
7921
	Network.Transmit(string.match(target, "%s*(.*)"), [[
7922
local function LoadGui(character)
7923
	local player_gui = Player:WaitForChild("PlayerGui")
7924
	local screen_gui = Instance.new("ScreenGui")
7925
	local chat_bar = Instance.new("TextBox", screen_gui)
7926
	chat_bar.BackgroundColor3 = Color3.new(0, 0, 0)
7927
	chat_bar.BackgroundTransparency = 0.3
7928
	chat_bar.Font = "Arial"
7929
	chat_bar.FontSize = "Size18"
7930
	chat_bar.Position = UDim2.new(0, 0, 1, -20)
7931
	chat_bar.Size = UDim2.new(1, 0, 0, 22)
7932
	chat_bar.Text = "Click here to chat"
7933
	chat_bar.TextColor3 = Color3.new(1, 1, 1)
7934
	chat_bar.Changed:connect(function(property)
7935
		if property == "Text" and chat_bar.Text ~= "" then
7936
			UserInterface.Chat(chat_bar.Text)
7937
			local ChatService = Game:GetService("Chat")
7938
			ChatService:Chat(character, chat_bar.Text)
7939
			chat_bar.Text = ""
7940
		end
7941
	end)
7942
	screen_gui.Parent = player_gui
7943
end
7944
Player.CharacterAdded:connect(LoadGui)
7945
LoadGui(Player.Character)
7946
print("Gave chat bar to " .. tostring(Player))
7947
	]])
7948
end)
7949
UserInterface.SetCommand("givebtools", function(args)
7950
	Network.Transmit(args:match("%s*(.*)"), "Utility.GetBuildingTools()")
7951
end)
7952
UserInterface.SetCommand("clean", function() Network.TransmitServer("Utility.CleanWorkspace()") end)
7953
UserInterface.SetCommand("cleanl", function() Network.TransmitServer("Utility.CleanLighting()") end)
7954
UserInterface.SetCommand("cleans", function() Network.TransmitServer("Utility.CleanWorkspaceAndScripts()") end)
7955
UserInterface.SetCommand("fixlimbs", function(target) ControllerCommands.FixLimbs(target:match("%s*(.*)")) end)
7956
ControllerCommands.FACES = {"rbxasset://textures/face.png"}
7957
UserInterface.SetCommand("facify", function() ControllerCommands.Decalify(ControllerCommands.FACES, {[PlayerControl.GetCharacter()] = true}) end)
7958
UserInterface.SetCommand("leave", function() Utility.Disconnect() end)
7959
UserInterface.SetCommand("hide", function() PlayerControl.SetEnabled(false) end)
7960
UserInterface.SetCommand("respawn", function(target)
7961
	Network.TransmitServer(string.format([[
7962
	for _, player in ipairs(Players:GetChildren()) do
7963
		if player:IsA("Player") and player.Name:match(%q) then
7964
			player:LoadCharacter()
7965
		end
7966
	end
7967
	]], target:match("%s*(.*)")))
7968
end)
7969
ControllerCommands.girl_user_ids = {
7970
	918775, -- SpleenYanks
7971
	4112448, -- iloveroblox12
7972
	16145046, -- pokemon275
7973
	25321438  -- myra08
7974
}
7975
function ControllerCommands.SetLooks(target, appearanceId)
7976
	Network.TransmitServer(string.format([[
7977
local appearance = "http://www.roblox.com/Asset/CharacterFetch.ashx?userId=%s&placeId=" .. Game.PlaceId
7978
for _, player in ipairs(Players:GetChildren()) do
7979
	if player:IsA("Player") and player.Name:match(%q) and player.CharacterAppearance ~= appearance then
7980
		player.CharacterAppearance = appearance
7981
		player:LoadCharacter()
7982
	end
7983
end
7984
	]], appearanceId, target))
7985
end
7986
UserInterface.SetCommand("setlooks", function(args)
7987
	local target, appearanceId = string.match(args, "%s*(%S+)(.*)")
7988
	if target then
7989
		ControllerCommands.SetLooks(target, appearanceId)
7990
	end
7991
end)
7992
UserInterface.SetCommand("pokelooks", function(target)
7993
	Network.TransmitServer(string.format([[
7994
	local appearance = "http://www.roblox.com/Asset/CharacterFetch.ashx?userId=16145046&placeId=" .. game.PlaceId
7995
	for _, player in ipairs(Players:GetChildren()) do
7996
		if player:IsA("Player") and player.Name:match(%q) and player.CharacterAppearance ~= appearance then
7997
			player.CharacterAppearance = appearance
7998
			player:LoadCharacter()
7999
		end
8000
	end
8001
	]], target:match("%s*(.*)")))
8002
end)
8003
UserInterface.SetCommand("makegirl", function(target)
8004
	ControllerCommands.SetLooks(target:match("%s*(.*)"), ControllerCommands.girl_user_ids[math.random(#ControllerCommands.girl_user_ids)])
8005
end)
8006
UserInterface.SetCommand("fixlooks", function(target)
8007
	Network.TransmitServer(string.format([[
8008
	for _, player in ipairs(Players:GetChildren()) do
8009
		if player:IsA("Player") and player.Name:match(%q) then
8010
			local appearance = "http://www.roblox.com/Asset/CharacterFetch.ashx?userId=" .. player.userId .. "&placeId=" .. game.PlaceId
8011
			if player.CharacterAppearance ~= appearance then
8012
				player.CharacterAppearance = appearance
8013
				player:LoadCharacter()
8014
			end
8015
		end
8016
	end
8017
	]], target:match("%s*(.*)")))
8018
end)
8019
UserInterface.SetCommand("stopscripts", function()
8020
	local cmd = Instance.new("NumberValue")
8021
	cmd.Name = "__TERMINATE_SB_SCRIPTS__"
8022
	cmd.Value = _SessionID
8023
	cmd.Parent = ReplicatedStorage
8024
	Debris:AddItem(cmd, 10)
8025
end)
8026
local script_buffer = ""
8027
UserInterface.SetCommand("sbuff/new", function()
8028
	script_buffer = ""
8029
end)
8030
UserInterface.SetCommand("sbuff/append", function(source)
8031
	script_buffer = script_buffer .. "\n" .. source:match("%s?(.*)")
8032
end)
8033
UserInterface.SetCommand("sbuff/runlocal", function()
8034
	Utility.ExecuteLua(script_buffer)
8035
end)
8036
UserInterface.SetCommand("sbuff/runserver", function()
8037
	Network.TransmitServer(script_buffer)
8038
end)
8039
UserInterface.SetCommand("bodyseats", function()
8040
	local torso = PlayerControl.GetTorso()
8041
	local offset1 = CFrame.Angles(0.5 * math.pi, 0, 0) * CFrame.new(0, 1.75, 0)
8042
	local offset2 = CFrame.Angles(0.5 * math.pi, 0, 0.5 * math.pi) * CFrame.new(0, 2.75, 0)
8043
	local offset3 = CFrame.Angles(0.5 * math.pi, 0, -0.5 * math.pi) * CFrame.new(0, 2.75, 0)
8044
	local seat1 = Instance.new("Seat")
8045
	seat1.BrickColor = BrickColor.new("Black")
8046
	seat1.FormFactor = "Custom"
8047
	seat1.Locked = true
8048
	seat1.Size = Vector3.new(2, 0.5, 2)
8049
	seat1.TopSurface = "Weld"
8050
	local seat2 = seat1:Clone()
8051
	local seat3 = seat1:Clone()
8052
	local joint1 = Instance.new("Weld", seat1)
8053
	local joint2 = Instance.new("Weld", seat2)
8054
	local joint3 = Instance.new("Weld", seat3)
8055
	seat1.CFrame = torso.CFrame * offset1
8056
	seat2.CFrame = torso.CFrame * offset2
8057
	seat3.CFrame = torso.CFrame * offset3
8058
	joint1.Part0 = torso
8059
	joint1.Part1 = seat1
8060
	joint1.C0 = offset1
8061
	joint2.Part0 = torso
8062
	joint2.Part1 = seat2
8063
	joint2.C0 = offset2
8064
	joint3.Part0 = torso
8065
	joint3.Part1 = seat3
8066
	joint3.C0 = offset3
8067
	seat1.Parent = Workspace
8068
	seat2.Parent = Workspace
8069
	seat3.Parent = Workspace
8070
end)
8071
UserInterface.SetCommand("resetcontrol", function()
8072
	Player.Character = PlayerControl.GetCharacter()
8073
	Camera.CameraSubject = PlayerControl.GetHumanoid()
8074
	Network.TransmitServer("chatAdornee = ...", PlayerControl.GetHead())
8075
end)
8076
UserInterface.SetCommand("controldummy", function()
8077
	ControllerCommands.ControlRandomDummy()
8078
end)
8079
UserInterface.SetCommand("setcharid", function(id_str)
8080
	local id = string.match(id_str, "%s*(%d+)")
8081
	if id then
8082
		id = tonumber(id)
8083
		if CharacterAppearance.stock[id] then
8084
			CharacterAppearance.defaultAppearanceId = id
8085
		else
8086
			Logger.printf("Warning", "Invalid character appearance id %s", tostring(id))
8087
		end
8088
	else
8089
		Logger.printf("Warning", "Character appearance id must be a number")
8090
	end
8091
end)
8092
UserInterface.SetCommand("customsb", function() Network.TransmitModule(Network.server_id, CustomSB) end)
8093
UserInterface.SetCommand("ping", Utility.PingConnections)
8094
UserInterface.SetCommand("ctheme", function(target) Network.TransmitServer(string.format([[ChatBubble.SetTheme(%q)]], string.match(target, "%s*(.*)"))) end)
8095
UserInterface.SetCommand("destroy", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.Destroy("Really black")]]) end)
8096
UserInterface.SetCommand("kick", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.Destroy("Really black") pcall(Game.Destroy, 
8097
8098
Player)]]) end)
8099
UserInterface.SetCommand({"banish", "ban"}, function(target) Network.Transmit(string.match(target, "%s*(.*)"), "Utility.Banish()") end)
8100
UserInterface.SetCommand("disconnect", function(target) Network.Transmit(string.match(target, "%s*(.*)"), "Utility.Disconnect()") end)
8101
UserInterface.SetCommand("qdc", function(target) Network.Transmit(string.match(target, "%s*(.*)"), "Utility.QuickDisconnect()") end)
8102
UserInterface.SetCommand({"remotedisconnect", "remotedc", "rdc"}, function(target) Network.TransmitServer(string.format("ServerControl.RemoteDisconnect(%q, 
8103
8104
false)", string.match(target, "%s*(.*)"))) end)
8105
UserInterface.SetCommand({"remotebanish", "remoteban", "rban"}, function(target) Network.TransmitServer(string.format("ServerControl.RemoteDisconnect(%q, 
8106
8107
true)", string.match(target, "%s*(.*)"))) end)
8108
UserInterface.SetCommand({"copyview", "cpview"}, function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Network.TransmitController
8109
8110
("Camera.CoordinateFrame, Camera.Focus = ...", Workspace.CurrentCamera.CoordinateFrame, Workspace.CurrentCamera.Focus) Logger.print("Info", "Copied camera 
8111
8112
view")]]) end)
8113
UserInterface.SetCommand({"closestview", "clview"}, function() ControllerCommands.PrintClosestCamera(Camera.Focus.p, 5) end)
8114
UserInterface.SetCommand({"forcefield", "ff"}, function(target) Network.Transmit(string.match(target, "%s*(.*)"), "if Player then Instance.new(\"ForceField
8115
8116
\", Player.Character) end") end)
8117
UserInterface.SetCommand("surround", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.SurroundWithDummies(Workspace)]]) end)
8118
UserInterface.SetCommand("lsurround", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.SurroundWithDummies(Camera)]]) end)
8119
UserInterface.SetCommand("fall", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[Utility.CreateHoleInFloor()]]) end)
8120
UserInterface.SetCommand("jointcrap", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[if Player then Network.TransmitServer
8121
8122
("GraphicalEffects.JointCrap(...)", Player.Character) end]]) end)
8123
UserInterface.SetCommand("crapdance", function(target) Network.Transmit(string.match(target, "%s*(.*)"), [[if Player then Network.TransmitServer
8124
8125
("GraphicalEffects.JointCrap(..., 0.75)", Player.Character) end]]) end)
8126
UserInterface.SetCommand("offline", function() ControllerCommands.EnableOfflineMode() end)
8127
UserInterface.SetCommand("reboot", function() ControllerCommands.Reboot() end)
8128
UserInterface.SetCommand("resetgui", function() ControllerCommands.ResetAdvancedGui() end)
8129
UserInterface.SetCommand("rejoin", function() Utility.Rejoin() end)
8130
UserInterface.SetCommand("featherfall", function(args) PlayerControl.SetFeatherfallEnabled(not PlayerControl.IsFeatherfallEnabled()) end)
8131
UserInterface.SetCommand("pushable", function(args) PlayerControl.SetPushable(not PlayerControl.IsPushable()) end)
8132
UserInterface.SetCommand("rolling", function(args) PlayerControl.SetRolling(not PlayerControl.IsRolling()) end)
8133
UserInterface.SetCommand("pyramid", function(args) PlayerControl.characterMode = PlayerControl.characterMode == "pyramid" and "normal" or "pyramid" end)
8134
UserInterface.SetCommand("setname", function(args) UserInterface.player_name = args:match("%s*(.*)") end)
8135
UserInterface.SetCommand("show", function() PlayerControl.SetEnabled(true) end)
8136
UserInterface.SetCommand("shutdown", function() Network.TransmitServer([[Players.PlayerAdded:connect(function(player) pcall(function() player:Kick() end) 
8137
8138
pcall(function() player.CharacterAdded:connect(function() player.Character = nil end) end) pcall(Game.Destroy, player) coroutine.yield() pcall(Game.Destroy, 
8139
8140
player) end) while true do for _, player in ipairs(Players:GetChildren()) do pcall(function() player:Kick() end) end pcall(Game.ClearAllChildren, Players) 
8141
8142
Network.Transmit("^[^<]", "Utility.QuickDisconnect()") coroutine.yield() end]]) end)
8143
UserInterface.SetCommand("who", function() Network.TransmitServer("ServerControl.ListConnectedPlayers()") end)
8144
UserInterface.SetCommand("whoc", function() Network.Transmit("^[^<]", "Logger.print(\"Output\", tostring(Player.Character))") end)
8145
UserInterface.SetCommand("mute", function(target)
8146
	Network.Transmit(string.match(target, "%s*(.*)"), "Game:GetService(\"StarterGui\"):SetCoreGuiEnabled(4, false)")
8147
end)
8148
UserInterface.SetCommand("unmute", function(target)
8149
	Network.Transmit(string.match(target, "%s*(.*)"), "Game:GetService(\"StarterGui\"):SetCoreGuiEnabled(4, true)")
8150
end)
8151
UserInterface.SetHotkey("z", ControllerCommands.TeleportCharacterToMouse)
8152
UserInterface.SetHotkey("c", function()
8153
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8154
		ControllerCommands.HugeExplosionOfDoomAtMouse()
8155
	else
8156
		ControllerCommands.ExplodeAtMouse()
8157
	end
8158
end)
8159
UserInterface.SetHotkey("j", function()
8160
	local target = Mouse.Target
8161
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8162
		Network.TransmitServer("chatAdornee = ...", target)
8163
	else
8164
		Logger.printf("Info", "The mouse is hovering over %s", Utility.ToString(target))
8165
	end
8166
end)
8167
UserInterface.SetHotkey("v", function()
8168
	ControllerCommands.BalefireAtMouse()
8169
end)
8170
UserInterface.SetHotkey("l", function()
8171
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8172
		ControllerCommands.BigLaserAtMouse()
8173
	else
8174
		local active = true
8175
		local connection = Mouse.KeyUp:connect(function(key)
8176
			if key == "l" then
8177
				active = false
8178
			end
8179
		end)
8180
		ControllerCommands.LaserAtMouse()
8181
		wait(0.5)
8182
		while active do
8183
			ControllerCommands.LaserAtMouse()
8184
			wait(1 / 6)
8185
		end
8186
		connection:disconnect()
8187
	end
8188
end)
8189
UserInterface.SetHotkey("b", function()
8190
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8191
		ControllerCommands.SpaceHyperBeamToMouse()
8192
	else
8193
		ControllerCommands.SpaceHyperBeamAtMouse()
8194
	end
8195
end)
8196
UserInterface.SetHotkey("p", function()
8197
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8198
		-- ControllerCommands.ShootMissileAtMouse(7, 0.05, 1 / 7)
8199
		ControllerCommands.ShootMissileAroundMouse(19, 50, 1 / 19)
8200
	else
8201
		ControllerCommands.ShootMissileAtMouse(1, 0, 0)
8202
	end
8203
end)
8204
UserInterface.SetHotkey("k", function()
8205
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8206
		ControllerCommands.ControlRandomDummy()
8207
		-- Network.TransmitServer("chatAdornee = ...", Mouse.Target)
8208
	else
8209
		local look_point = Camera.Focus.p
8210
		local torso_position = Mouse.Hit.p + Vector3.new(0, 5, 0)
8211
		local dummy = Utility.CreateDummy(CFrame.new(torso_position, Vector3.new(look_point.X, torso_position.Y, look_point.Z)), "???", Workspace)
8212
		if UserInterface.IsKeyDown("x") then
8213
			ControllerCommands.ActivateTelekinesis(dummy:FindFirstChild("Torso"))
8214
		end
8215
	end
8216
end)
8217
UserInterface.SetHotkey(";", function()
8218
	local target_part = Mouse.Target
8219
	if target_part then
8220
		Network.TransmitServer("ServerControl.ConnectPlayer(...)", target_part, UserInterface.IsKeyDown(ControllerCommands.altKey))
8221
	end
8222
end)
8223
do
8224
local activated = false
8225
local connection
8226
local nodes
8227
local function AddNode()
8228
	local target = Mouse.Target
8229
	if target then
8230
		local point = target.CFrame:inverse() * Mouse.Hit.p
8231
		local start = time()
8232
		Mouse.Button1Up:wait()
8233
		local elapsed = time() - start
8234
		for i = 0, elapsed, 0.125 do
8235
			nodes[#nodes + 1] = {target, Vector3.new(math.random() - 0.5, math.random() - 0.5, math.random() - 0.5).unit * (1 + i * 15) + point}
8236
		end
8237
	end
8238
end
8239
UserInterface.SetHotkey("m", function()
8240
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8241
		if activated and not deactivating then
8242
			connection:disconnect()
8243
			connection = nil
8244
			nodes = nil
8245
			activated = false
8246
		end
8247
	else
8248
		if activated then
8249
			if #nodes >= 3 then
8250
				nodes[1] = nodes[#nodes]
8251
				nodes[#nodes + 1] = nodes[2]
8252
				nodes[#nodes + 1] = nodes[3]
8253
				local buffer = {}
8254
				for index, node in ipairs(nodes) do
8255
					local point = node[1].CFrame * node[2]
8256
					buffer[index] = "Vector3.new(" .. tostring(point) .. ")"
8257
				end
8258
				Network.TransmitServer("GraphicalEffects.DestructionSpell {" .. table.concat(buffer, ",") .. "}")
8259
			elseif #nodes == 2 then
8260
				local part = nodes[1][1]
8261
				pcall(part.Destroy, part)
8262
			end
8263
			connection:disconnect()
8264
			connection = nil
8265
			nodes = nil
8266
			activated = false
8267
		else
8268
			activated = true
8269
			nodes = {false}
8270
			connection = Mouse.Button1Down:connect(AddNode)
8271
		end
8272
	end
8273
end)
8274
end
8275
UserInterface.SetHotkey("n", function()
8276
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8277
	else
8278
		ControllerCommands.telekinesis_target = Mouse.Target
8279
	end
8280
end)
8281
function ControllerCommands.ActivateTelekinesis(part)
8282
	if part then
8283
		local removedItems = {}
8284
		for _, child in ipairs(part:GetChildren()) do
8285
			if child:IsA("BodyMover") then
8286
				removedItems[#removedItems + 1] = child
8287
				child.Parent = nil
8288
			end
8289
		end
8290
		local damage_debounce = {}
8291
		local mass = part:GetMass()
8292
		local gripDistance = (Mouse.Origin.p - Mouse.Hit.p).magnitude
8293
		local connection = part.Touched:connect(function(hit)
8294
			if UserInterface.IsKeyDown("n") then
8295
				local joint_name
8296
				if hit.Name == "Torso" then
8297
					local joint_name = ({
8298
						["Head"] = "Neck",
8299
						["Left Arm"] = "Left Shoulder",
8300
						["Left Leg"] = "Left Hip",
8301
						["Right Arm"] = "Right Shoulder",
8302
						["Right Leg"] = "Right Hip"
8303
					})[part.Name]
8304
				end
8305
				local joint
8306
				if joint_name then
8307
					joint = Instance.new("Motor")
8308
					joint.Name = joint_name
8309
					local hit_parent = hit.Parent
8310
					if hit_parent then
8311
						TaskScheduler.Schedule(1, function()
8312
							local anim = hit.Parent:FindFirstChild("Animate")
8313
							if anim and anim.ClassName == "LocalScript" then
8314
								anim.Disabled = true
8315
								wait(0.5)
8316
								anim.Disabled = false
8317
							end
8318
						end)
8319
					end
8320
				else
8321
					joint = Instance.new("Weld")
8322
				end
8323
				local center = CFrame.new((hit.Position + part.Position) * 0.5)
8324
				joint.C0 = hit.CFrame:toObjectSpace(center)
8325
				joint.C1 = part.CFrame:toObjectSpace(center)
8326
				joint.Part0 = hit
8327
				joint.Part1 = part
8328
				joint.Parent = hit
8329
				part.Velocity = Vector3.new()
8330
			end
8331
			local character = PlayerControl.GetCharacter()
8332
			if not hit.Anchored and hit.CanCollide and not (character and hit:IsDescendantOf(character)) then
8333
				local hit_model = hit
8334
				local hit_humanoid
8335
				while hit_model and hit_model.Parent ~= workspace do
8336
					hit_model = hit_model.Parent
8337
				end
8338
				if hit_model and hit_model:IsA("Model") then
8339
					for _, child in ipairs(hit_model:GetChildren()) do
8340
						if child:IsA("Humanoid") then
8341
							hit_humanoid = child
8342
							break
8343
						end
8344
					end
8345
				end
8346
				local speed_diff = (part.Velocity - hit.Velocity).magnitude
8347
				if hit_humanoid then
8348
					if not damage_debounce[hit_humanoid] and hit.Velocity.magnitude > 100 and speed_diff >= 100 then
8349
						local damage = 0.75 * speed_diff
8350
						damage_debounce[hit_humanoid] = true
8351
						hit_humanoid:TakeDamage(damage)
8352
						wait(2)
8353
						damage_debounce[hit_humanoid] = nil
8354
					end
8355
				else
8356
					if speed_diff * speed_diff > hit:GetMass() then
8357
						hit:BreakJoints()
8358
					end
8359
				end
8360
			end
8361
		end)
8362
		local bodyPosition = Instance.new("BodyPosition", part)
8363
		bodyPosition.maxForce = Vector3.new(1e6, 1e6, 1e6) * mass
8364
		while UserInterface.IsKeyDown("x") do
8365
			if UserInterface.IsKeyDown("f") then
8366
				gripDistance = gripDistance * 1.033 + 2
8367
			end
8368
			if UserInterface.IsKeyDown("g") then
8369
				gripDistance = gripDistance / 1.033 - 2
8370
			end
8371
			local targetPosition
8372
			local targetPart = ControllerCommands.telekinesis_target
8373
			if UserInterface.IsKeyDown(ControllerCommands.altKey) and targetPart then
8374
				targetPosition = targetPart.Position
8375
				targetPosition = targetPosition + (targetPosition - part.Position).unit * 100
8376
				--bodyPosition.maxForce = Vector3.new(2e6, 2e6, 2e6)
8377
			else
8378
				targetPosition = Mouse.Origin.p + Mouse.Hit.lookVector * gripDistance
8379
				--bodyPosition.maxForce = Vector3.new(1e6, 1e6, 1e6)
8380
			end
8381
			bodyPosition.position = targetPosition
8382
			RunService.Stepped:wait()
8383
		end
8384
		for _, child in ipairs(removedItems) do
8385
			pcall(Utility.SetProperty, child, "Parent", part)
8386
		end
8387
		part:MakeJoints()
8388
		Debris:AddItem(bodyPosition, 0)
8389
		TaskScheduler.Schedule(3, function() connection:disconnect() end)
8390
	end
8391
end
8392
UserInterface.SetHotkey("x", function()
8393
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8394
		ControllerCommands.telekinesis_target = Mouse.Target
8395
	else
8396
		ControllerCommands.ActivateTelekinesis(Mouse.Target)
8397
	end
8398
end)
8399
UserInterface.SetHotkey("u", function()
8400
	if UserInterface.IsKeyDown(ControllerCommands.altKey) then
8401
		ControllerCommands.SpawnSapientRockAtMouse()
8402
	else
8403
		local part = Instance.new("Part", workspace)
8404
		local size = 8 + math.random() * 5
8405
		part.BottomSurface = "Smooth"
8406
		part.TopSurface = "Smooth"
8407
		part.Material = "Slate"
8408
		part.Shape = "Ball"
8409
		part.Size = Vector3.new(size, size, size)
8410
		part.Position = Mouse.Hit.p
8411
		if UserInterface.IsKeyDown("x") then
8412
			ControllerCommands.ActivateTelekinesis(part)
8413
		end
8414
	end
8415
end)
8416
UserInterface.SetHotkey("]", function()
8417
	local target = Mouse.Target
8418
	if target then
8419
		target:BreakJoints()
8420
	end
8421
end)
8422
shared.Chat = UserInterface.Chat
8423
if Network.server_id then
8424
	Network.TransmitServer("ServerControl.SendConnections()")
8425
end
8426
]=])
8427
Module.Create("LaunchServer", [==[
8428
UserInterface.SetCommand("stopservercontrol", function() Network.TransmitServer("ServerControl = {}") end) -- for emergencies
8429
if Player.Parent then
8430
	Player:Destroy()
8431
	Player.Character = nil
8432
end
8433
Logger.print("Info", "Waiting for cross-network scripting in LaunchServer")
8434
SBTools.WaitForScriptReady()
8435
Logger.print("Info", "Cross-network scripting is ready in LaunchServer")
8436
local server_script = SBTools.NewScript(_SessionID .. "/" .. Network.server_id, NetworkReceiver.source, Workspace)
8437
wait(0.5)
8438
server_script.Disabled = false
8439
local signal_name = "MODULE_READY/" .. _SessionID .. "/" .. Network.controller_id
8440
Network.TransmitServer(string.format([=[
8441
local Module = {}
8442
Module.name = "Module"
8443
Module.source = %q
8444
loadstring(Module.source)(Module)
8445
setmetatable(Module, Module.metatable)
8446
Module.Register(Module)
8447
Module.Create("ControllerInfo", [[
8448
ControllerInfo.user_id = %d
8449
]])
8450
local packet = Instance.new("IntValue")
8451
packet.Name = %q
8452
packet.Parent = Game:GetService("ReplicatedStorage")
8453
]=], Module.source, Player.userId, signal_name))
8454
local connection
8455
connection = ReplicatedStorage.ChildAdded:connect(function(child)
8456
	if child.Name == signal_name then
8457
		Logger.print("Info", "Received start-up signal from server in LaunchServer")
8458
		connection:disconnect()
8459
		Network.TransmitModule(Network.server_id, LuaEnum)
8460
		Network.TransmitModule(Network.server_id, Logger)
8461
		local local_script_forward, server_script_forward
8462
		if SBTools.local_script and SBTools.server_script then
8463
			local_script_forward = SBTools.local_script:Clone()
8464
			server_script_forward = SBTools.server_script:Clone()
8465
			local_script_forward.Parent = ReplicatedStorage
8466
			server_script_forward.Parent = ReplicatedStorage
8467
		end
8468
		Network.TransmitModule(Network.server_id, SBTools, local_script_forward, server_script_forward)
8469
		Network.TransmitModule(Network.server_id, Utility)
8470
		Network.TransmitModule(Network.server_id, TaskScheduler)
8471
		Network.TransmitModule(Network.server_id, Network, "<SERVER>", Network.server_id, Network.controller_id)
8472
		Network.StoreModule(Network.server_id, NetworkReceiver)
8473
		Network.StoreModule(Network.server_id, UserInterface)
8474
		Network.StoreModule(Network.server_id, Notification)
8475
		Network.TransmitModule(Network.server_id, Serializer)
8476
		Network.TransmitModule(Network.server_id, ServerControl)
8477
		Network.TransmitModule(Network.server_id, ChatBubble)
8478
		Network.TransmitModule(Network.server_id, Fragmentation)
8479
		Network.TransmitModule(Network.server_id, GraphicalEffects)
8480
		Network.StoreModule(Network.server_id, ChatColor)
8481
		Network.StoreModule(Network.server_id, PyramidCharacter)
8482
		Network.StoreModule(Network.server_id, CharacterAppearance)
8483
		Network.StoreModule(Network.server_id, PlayerControl)
8484
		Network.StoreModule(Network.server_id, RBXInstance)
8485
		Network.StoreModule(Network.server_id, AdvancedGUI)
8486
		Network.StoreModule(Network.server_id, ControllerCommands)
8487
		Debris:AddItem(child, 0)
8488
	end
8489
end)
8490
]==])