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