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