diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 0000000000..038fd4fc48
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,4 @@
+((nil . ((indent-tab-mode . t)
+ (tab-width . 4)
+ (coding-system-for-write . unix)
+ (coding-system-for-read . unix)))
diff --git a/.sublime-project b/.sublime-project
new file mode 100644
index 0000000000..408623cd35
--- /dev/null
+++ b/.sublime-project
@@ -0,0 +1,15 @@
+{
+ "folders":
+ [
+ {
+ "path": "."
+ }
+ ],
+ "settings":
+ {
+ "translate_tabs_to_spaces": false,
+ "tab_size": 4,
+ "detect_indentation": false,
+ "default_line_endings": "unix"
+ }
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000..838e2ee050
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,9 @@
+{
+ "editor.tabSize": 4,
+ "editor.insertSpaces": false,
+ "editor.detectIndentation": false,
+ "files.eol": "\n",
+ "[yaml]": {
+ "editor.detectIndentation": true
+ }
+}
diff --git a/Loader/Config/Settings.luau b/Loader/Config/Settings.luau
index 678850d405..b3b7eb4d7e 100644
--- a/Loader/Config/Settings.luau
+++ b/Loader/Config/Settings.luau
@@ -61,8 +61,9 @@ local descs = {}; --// Contains settings descriptions
If I wanted to make it so rank 134 in group 1029934 and BobJenkins123 had mod admin I would do
settings.Moderators = {"Group:1029943:134", "BobJenkins123"}
-
- I was going to change the admin rank stuff but I figured it would confuse people too much, so I left it as mods/admins/HeadAdmins ;p
+ !NOTE! When adding a group to a table, you may be tempted to replace the word Group with the name of your group – DON'T.
+ The group name is IRRELEVANT! If one's group was named 2Drool4School and it had the ID 2847031, the correct form is {"Group:2847031"}
+ and not {"2Drool4School:2847031"}
--// Admins
@@ -283,17 +284,18 @@ settings.CommandCooldowns = {
]]
}
-settings.FunCommands = true -- Are fun commands enabled?
-settings.PlayerCommands = true -- Are player-level utility commands enabled?
-settings.AgeRestrictedCommands = true -- Are age-locked commands enabled?
-settings.WarnDangerousCommand = false -- Do dangerous commands ask for confirmation?
-settings.CommandFeedback = false -- Should players be notified when commands with non-obvious effects are run on them?
-settings.CrossServerCommands = true -- Are commands which affect more than one server enabled?
-settings.ChatCommands = true -- If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands
-settings.CreatorPowers = true -- Gives me creator-level admin; This is strictly used for debugging; I can't debug without full access to the script
-settings.CodeExecution = false -- Enables the use of code execution in Adonis. Scripting related (such as ;s) and a few other commands require this
-settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command
+settings.FunCommands = true -- Are fun commands enabled?
+settings.PlayerCommands = true -- Are player-level utility commands enabled?
+settings.AgeRestrictedCommands = true -- Are age-locked commands enabled?
+settings.WarnDangerousCommand = false -- Do dangerous commands ask for confirmation?
+settings.CommandFeedback = false -- Should players be notified when commands with non-obvious effects are run on them?
+settings.CrossServerCommands = true -- Are commands which affect more than one server enabled?
+settings.ChatCommands = true -- If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands
+settings.CreatorPowers = true -- Gives me creator-level admin; This is strictly used for debugging; I can't debug without full access to the script
+settings.CodeExecution = false -- Enables the use of code execution in Adonis. Scripting related (such as ;s) and a few other commands require this
+settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command
settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false.
+settings.ChatCreateRobloxCommands = false -- Whether "/" commands for Roblox should get created in new Chat
settings.BanMessage = "Banned" -- Message shown to banned users upon kick
settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is ;slocked
diff --git a/MainModule/Client/Core/Process.luau b/MainModule/Client/Core/Process.luau
index 0b868b7ed2..ecc3853671 100644
--- a/MainModule/Client/Core/Process.luau
+++ b/MainModule/Client/Core/Process.luau
@@ -67,7 +67,11 @@ return function(Vargs, GetEnv)
Process.RateLimits = Remote.Get("RateLimits") or Process.RateLimits;
--// Hide TextChatComands
- Process.HandleTextChatCommands()
+ task.defer(function()
+ if Remote.Get("Variable", "ChatCreateRobloxCommands") then
+ Process.HandleTextChatCommands()
+ end
+ end)
Process.RunAfterLoaded = nil;
end
diff --git a/MainModule/Client/UI/Modern/Window.rbxm b/MainModule/Client/UI/Modern/Window.rbxm
deleted file mode 100644
index ef4de2ddde..0000000000
Binary files a/MainModule/Client/UI/Modern/Window.rbxm and /dev/null differ
diff --git a/MainModule/Client/UI/Modern/Window.rbxmx b/MainModule/Client/UI/Modern/Window.rbxmx
new file mode 100644
index 0000000000..1a0205ae72
--- /dev/null
+++ b/MainModule/Client/UI/Modern/Window.rbxmx
@@ -0,0 +1,6038 @@
+
+ true
+ null
+ nil
+ -
+
+
+ false
+ 0
+ true
+ false
+ 9000
+ false
+ Window
+ false
+
[null]
+ 1
+ 2
+ 0
+ 0
+ 0
+ 0
+ false
+ -1
+
+ 0
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.639215708
+ 0.635294139
+ 0.647058845
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ StringEntry
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 0
+ 0
+ 20
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -10
+ 0
+ 20
+
+ 0
+ -1
+
+ String:
+
+ 1
+ 1
+ 1
+
+ 0
+ true
+ 24
+
+ 0
+ 0
+ 0
+
+ 0.800000012
+ -7.30156913e-08
+ 0
+ true
+ 0
+ 0
+ false
+ 2
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ true
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Box
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0.699999988
+ 0.699999988
+ 0.699999988
+
+
+
+ 1
+ -100
+ 0
+ 0
+
+ false
+ [null]
+ 0
+ true
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+ true
+
+ 0
+ 100
+ 1
+ 0
+
+ 0
+ -1
+
+ Text
+
+ 1
+ 1
+ 1
+
+ 0
+ true
+ false
+ 18
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ true
+ 1
+ 1
+ true
+ 2
+
+
+ -
+
+
+ 0
+ false
+ Desc
+ -1
+
+ TestDesc
+
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+ true
+ 0
+ Slider
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 0.75
+ 0
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ 0
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ false
+ 2
+
+ -
+
+
+ 0
+ false
+ Percentage
+ -1
+
+ 0
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ true
+ true
+ 0
+ Drag
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ -10
+ 0.5
+ -10
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 20
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ true
+ 2
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+ rbxassetid://118129065
+
+ 0.921568692
+ 0.921568692
+ 0.921568692
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 0
+ true
+ 0
+ Slider
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ -10
+ 0.5
+ -10
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 20
+ 0
+ 20
+
+ 0
+
+
+ 100
+ 100
+
+
+ 100
+ 100
+
+
+ 1
+ -1
+
+
+ 1
+ 0
+ 1
+ 0
+
+ true
+ 2
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+ rbxassetid://939118523
+
+ 1
+ 1
+ 1
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 0.300000012
+ true
+ 0
+ SliderBar
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 0.5
+ -10
+
+ 0
+ [null]
+ 0
+ 1
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ 0
+ 0
+ 20
+
+ 0
+
+
+ 500
+ 100
+
+
+ 500
+ 100
+
+
+ 1
+ -1
+
+
+ 1
+ 0
+ 1
+ 0
+
+ true
+ 2
+
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.188235313
+ 0.188235313
+ 0.188235313
+
+ 0
+
+ 0.301960796
+ 0.301960796
+ 0.301960796
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+ true
+ 0
+ Dropdown
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0.75
+ 0
+ 0.25
+ 0
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 150
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ false
+ 1
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.207843155
+ 0.207843155
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/SourceSansPro.json
+ 600
+
+ rbxasset://fonts/SourceSansPro-Semibold.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ dSelected
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 0
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ true
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -20
+ 1
+ 0
+
+ 0
+ -1
+ 0
+
+ Selected Option
+
+ 0.933333397
+ 0.933333397
+ 0.933333397
+
+ 0
+ false
+ 16
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ true
+ 2
+ 1
+ true
+ 1
+
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://1317396937
+
+ 1
+ 1
+ 1
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 0
+ true
+ 0
+ false
+ Down
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 1
+ -20
+ 0.5
+ -10
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 20
+ 0
+ 20
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ true
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.129411772
+ 0.129411772
+ 0.129411772
+
+ 0
+
+ 0.301960796
+ 0.301960796
+ 0.301960796
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+ true
+ 0
+ Menu
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 1
+ 0
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ 0
+ 0
+ 100
+
+ 0
+ -1
+ 0
+
+ true
+ 1
+
+
+
+ -
+
+
+ 0
+ false
+ Config
+ -1
+
+
+
-
+
+
+ 0
+ false
+ CanKeepAlive
+ -1
+
+ true
+
+
+ -
+
+
+ 0
+ false
+ AllowMultiple
+ -1
+
+ true
+
+
+ -
+
+
+ 0
+ false
+
+ NoEnv-Code
+ {7148E0DE-E52B-4D1B-9515-0BFBD39286A0}
+ 0 and (y - 6 - sizeY) or (y)
+
+ point.Size = UDim2.fromOffset(sizeX, sizeY)
+ point.Position = UDim2.fromOffset(posX, posY)
+ point.Visible = text ~= ""
+ end)
+ end
+ end
+
+ function getNextPos(frame)
+ local farXChild, farYChild
+ for i,v in ipairs(frame:GetChildren()) do
+ if checkProperty(v, "Size") then
+ if not farXChild or (v.AbsolutePosition.X + v.AbsoluteSize.X) > (farXChild.AbsolutePosition.X + farXChild.AbsoluteSize.X) then
+ farXChild = v
+ end
+
+ if not farYChild or (v.AbsolutePosition.Y + v.AbsoluteSize.Y) > (farXChild.AbsolutePosition.Y + farXChild.AbsoluteSize.Y) then
+ farYChild = v
+ end
+ end
+ end
+
+ return ((not farXChild or not farYChild) and UDim2.new(0,0,0,0)) or UDim2.new(farXChild.Position.X.Scale, farXChild.Position.X.Offset + farXChild.AbsoluteSize.X, farYChild.Position.Y.Scale, farYChild.Position.Y.Offset + farYChild.AbsoluteSize.Y)
+ end
+
+ function LoadChildren(Obj, Children)
+ if Children then
+ local runWhenDone = Children.RunWhenDone and functionify(Children.RunWhenDone, Obj)
+ for class,data in pairs(Children) do
+ if type(data) == "table" then
+ if not data.Parent then data.Parent = Obj end
+ create(data.Class or data.ClassName or class, data)
+ elseif type(data) == "function" or type(data) == "string" and not runWhenDone then
+ runWhenDone = functionify(data, Obj)
+ end
+ end
+
+ if runWhenDone then
+ runWhenDone(Obj)
+ end
+ end
+ end
+
+ function BringToFront()
+ for i,v in ipairs(Player.PlayerGui:GetChildren()) do
+ if v:FindFirstChild("__ADONIS_WINDOW") then
+ v.DisplayOrder = 100
+ end
+ end
+
+ GUI.DisplayOrder = 101
+ end
+
+ function addTitleButton(data)
+ local startPos = 1
+ local realPos
+ local new
+ local original = Hide
+ local diff = (Hide.AbsolutePosition.X + Hide.AbsoluteSize.X) - Close.AbsolutePosition.X;
+ local far = Close;
+
+ for i,obj in ipairs(Drag:GetChildren()) do
+ if obj:IsA("TextButton") then
+ if obj.Visible and obj.AbsolutePosition.X < far.AbsolutePosition.X then
+ far = obj;
+ end
+ end
+ end;
+
+ local size = data.Size or original.Size;
+ local xPos = far.Position.X.Offset - (size.X.Offset - diff);
+ realPos = UDim2.new(far.Position.X.Scale, xPos, original.Position.Y.Scale, original.Position.Y.Offset)
+
+ data.Name = "__TITLEBUTTON"
+ data.Size = size
+ data.Parent = Drag
+ data.ZIndex = data.ZIndex or original.ZIndex
+ data.Position = data.Position or realPos
+ data.TextSize = data.TextSize or original.TextSize
+ data.TextColor3 = data.TextColor3 or original.TextColor3
+ data.TextScaled = data.TextScaled or original.TextScaled
+ data.TextScaled = data.TextScaled or original.TextScaled
+ data.TextWrapped = data.TextWrapped or original.TextWrapped
+ data.TextStrokeColor3 = data.TextStrokeColor3 or original.TextStrokeColor3
+ data.TextTransparency = data.TextTransparency or original.TextTransparency
+ data.TextStrokeTransparency = data.TextStrokeTransparency or original.TextStrokeTransparency
+ data.BackgroundTransparency = data.BackgroundTransparency or original.BackgroundTransparency
+ data.BackgroundColor3 = data.BackgroundColor3 or original.BackgroundColor3
+ data.BorderSizePixel = data.BorderSizePixel or original.BorderSizePixel
+ --data.TextXAlignment = data.TextXAlignment or original.TextXAlignment
+ --data.TextYAlignment = data.TextYAlignment or original.TextYAlignment
+ data.Font = data.Font or original.Font
+
+ return create("TextButton", data)
+ end
+
+ function functionify(func, object)
+ if type(func) == "string" then
+ if object then
+ local env = GetEnv()
+ env.Object = object
+ return client.Core.LoadCode(func, env)
+ else
+ return client.Core.LoadCode(func)
+ end
+ else
+ return func
+ end
+ end
+
+ function create(class, dataFound, existing)
+ local data = dataFound or {}
+ local class = data.Class or data.ClassName or class
+ local new = existing or (specialInsts[class] and specialInsts[class]:Clone()) or service.New(class)
+ local parent = data.Parent or new.Parent
+
+ if dataFound then
+ data.Parent = nil
+
+ if data.Class or data.ClassName then
+ data.Class = nil
+ data.ClassName = nil
+ end
+
+ if not data.BorderColor3 and checkProperty(new, "BorderColor3") then
+ new.BorderColor3 = dBorder
+ end
+
+ if not data.CanvasSize and checkProperty(new, "CanvasSize") then
+ new.CanvasSize = dCanvasSize
+ end
+
+ if not data.BorderSizePixel and checkProperty(new, "BorderSizePixel") then
+ new.BorderSizePixel = dPixelSize
+ end
+
+ if not data.BackgroundColor3 and checkProperty(new, "BackgroundColor3") then
+ new.BackgroundColor3 = dBackground
+ end
+
+ if not data.PlaceholderColor3 and checkProperty(new, "PlaceholderColor3") then
+ new.PlaceholderColor3 = dPlaceholderColor
+ end
+
+ if not data.Transparency and not data.BackgroundTransparency and checkProperty(new, "Transparency") and checkProperty(new, "BackgroundTransparency") then
+ new.BackgroundTransparency = dTransparency
+ elseif data.Transparency and checkProperty(new, "BackgroundTransparency") then
+ new.BackgroundTransparency = data.Transparency
+ end
+
+ if not data.TextColor3 and not data.TextColor and checkProperty(new, "TextColor3") then
+ new.TextColor3 = dTextColor
+ elseif data.TextColor then
+ new.TextColor3 = data.TextColor
+ end
+
+ if not data.Font and checkProperty(new, "Font") then
+ data.Font = dFont
+ end
+
+ if not data.TextSize and checkProperty(new, "TextSize") then
+ data.TextSize = dTextSize
+ end
+
+ if not data.BottomImage and not data.MidImage and not data.TopImage and class == "ScrollingFrame" then
+ new.BottomImage = dScrollImage
+ new.MidImage = dScrollImage
+ new.TopImage = dScrollImage
+ end
+
+ if not data.Size and checkProperty(new, "Size") then
+ new.Size = dSize
+ end
+
+ if not data.Position and checkProperty(new, "Position") then
+ new.Position = dPosition
+ end
+
+ if not data.ZIndex and checkProperty(new, "ZIndex") then
+ new.ZIndex = dZIndex
+ if parent and checkProperty(parent, "ZIndex") then
+ new.ZIndex = parent.ZIndex
+ end
+ end
+
+ if data.TextChanged and class == "TextBox" then
+ local textChanged = functionify(data.TextChanged, new)
+ new.FocusLost:Connect(function(enterPressed)
+ textChanged(new.Text, enterPressed, new)
+ end)
+ end
+
+ if (data.OnClicked or data.OnClick) and (class == "TextButton" or class == "ImageButton") then
+ local debounce = false;
+ local doDebounce = data.Debounce;
+ local onClick = functionify((data.OnClicked or data.OnClick), new)
+ new.MouseButton1Down:Connect(function()
+ if not debounce then
+ if doDebounce then
+ debounce = true
+ end
+
+ onClick(new)
+
+ debounce = false
+ end
+ end)
+ end
+
+ if data.Events then
+ for event,func in pairs(data.Events) do
+ local realFunc = functionify(func, new)
+ Event(new[event], function(...)
+ realFunc(...)
+ end)
+ end
+ end
+
+ if data.Visible == nil then
+ data.Visible = true
+ end
+
+ if data.LabelProps then
+ data.LabelProperties = data.LabelProps
+ end
+ end
+
+ if class == "Entry" then
+ local label = new.Text
+ local dots = new.Dots
+ local desc = new.Desc
+ local richText = data.RichText or label.RichText
+
+ label.ZIndex = data.ZIndex or new.ZIndex
+ dots.ZIndex = data.ZIndex or new.ZIndex
+
+ if data.Text then
+ label.Text = data.Text
+ label.Visible = true
+ data.Text = nil
+ end
+
+ if data.Desc or data.ToolTip then
+ desc.Value = data.Desc or data.ToolTip
+ data.Desc = nil
+ end
+
+ Expand(new, Tooltip, nil, richText)
+ else
+ if data.ToolTip then
+ Expand(new, Tooltip, data.ToolTip, data.RichText)
+ end
+ end
+
+ if class == "ButtonEntry" then
+ local button = new.Button
+ local debounce = false
+ local onClicked = functionify(data.OnClicked, button)
+
+ new:SetSpecial("DoClick",function()
+ if not debounce then
+ debounce = true
+ if onClicked then
+ onClicked(button)
+ end
+ debounce = false
+ end
+ end)
+
+ new.Text = data.Text or new.Text
+ button.ZIndex = data.ZIndex or new.ZIndex
+ button.MouseButton1Down:Connect(new.DoClick)
+ end
+
+ if class == "Boolean" then
+ local enabled = data.Enabled
+ local debounce = false
+ local onToggle = functionify(data.OnToggle, new)
+ local function toggle(isEnabled)
+ if not debounce then
+ debounce = true
+ if (isEnabled ~= nil and isEnabled) or (isEnabled == nil and enabled) then
+ enabled = false
+ new.Text = "Disabled"
+ elseif (isEnabled ~= nil and isEnabled == false) or (isEnabled == nil and not enabled) then
+ enabled = true
+ new.Text = "Enabled"
+ end
+
+ if onToggle then
+ onToggle(enabled, new)
+ end
+ debounce = false
+ end
+ end
+
+ --new.ZIndex = data.ZIndex
+ new.Text = (enabled and "Enabled") or "Disabled"
+ new.MouseButton1Down:Connect(function()
+ if onToggle then
+ toggle()
+ end
+ end)
+
+ new:SetSpecial("Toggle",function(ignore, isEnabled) toggle(isEnabled) end)
+ end
+
+ if class == "StringEntry" then
+ local box = new.Box
+ local ignore
+
+ new.Text = data.Text or new.Text
+ box.ZIndex = data.ZIndex or new.ZIndex
+
+ if data.BoxText then
+ box.Text = data.BoxText
+ end
+
+ if data.BoxProperties then
+ for i,v in pairs(data.BoxProperties) do
+ if checkProperty(box, i) then
+ box[i] = v
+ end
+ end
+ end
+
+ if data.TextChanged then
+ local textChanged = functionify(data.TextChanged, box)
+ box.Changed:Connect(function(p)
+ if p == "Text" and not ignore then
+ textChanged(box.Text)
+ end
+ end)
+
+ box.FocusLost:Connect(function(enter)
+ local change = textChanged(box.Text, true, enter)
+ if change then
+ ignore = true
+ box.Text = change
+ ignore = false
+ end
+ end)
+ end
+
+ new:SetSpecial("SetValue",function(ignore, newValue) box.Text = newValue end)
+ end
+
+ if class == "Slider" then
+ local mouseIsIn = false
+ local posValue = new.Percentage
+ local slider = new.Slider
+ local bar = new.SliderBar
+ local drag = new.Drag
+ local moving = false
+ local value = 0
+ local onSlide = functionify(data.OnSlide, new)
+
+ bar.ZIndex = data.ZIndex or new.ZIndex
+ slider.ZIndex = bar.ZIndex+1
+ drag.ZIndex = slider.ZIndex+1
+ drag.Active = true
+
+ if data.Value then
+ slider.Position = UDim2.new(0.5, -10, 0.5, -10)
+ drag.Position = slider.Position
+ end
+
+ bar.InputBegan:Connect(function(input)
+ if not moving and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then
+ value = ((input.Position.X)-(new.AbsolutePosition.X))/(new.AbsoluteSize.X)
+
+ if value < 0 then
+ value = 0
+ elseif value > 1 then
+ value = 1
+ end
+
+ slider.Position = UDim2.new(value, -10, 0.5, -10)
+ drag.Position = slider.Position
+ posValue.Value = value
+
+ if onSlide then
+ onSlide(value)
+ end
+ end
+ end)
+
+ drag.DragBegin:Connect(function()
+ moving = true
+ end)
+
+ drag.DragStopped:Connect(function()
+ moving = false
+ drag.Position = slider.Position
+ end)
+
+ drag.Changed:Connect(function()
+ if moving then
+ value = ((Mouse.X)-(new.AbsolutePosition.X))/(new.AbsoluteSize.X)
+
+ if value < 0 then
+ value = 0
+ elseif value > 1 then
+ value = 1
+ end
+
+ slider.Position = UDim2.new(value, -10, 0.5, -10)
+ posValue.Value = value
+
+ if onSlide then
+ onSlide(value)
+ end
+ end
+ end)
+
+ new:SetSpecial("SetValue",function(ignore, newValue)
+ if newValue and tonumber(newValue) then
+ value = tonumber(newValue)
+ posValue.Value = value
+ slider.Position = UDim2.new(value, -10, 0.5, -10)
+ drag.Position = slider.Position
+ end
+ end)
+ end
+
+ if class == "Dropdown" then
+ local menu = new.Menu
+ local downImg = new.Down
+ local selected = new.dSelected
+ local options = data.Options
+ local curSelected = data.Selected or data.Selection
+ local onSelect = functionify(data.OnSelection or data.OnSelect or function()end)
+ local textProps = data.TextProperties
+ local scroller = create("ScrollingFrame", {
+ Parent = menu;
+ Size = UDim2.fromScale(1, 1);
+ Position = UDim2.new();
+ BackgroundTransparency = 1;
+ ZIndex = 100;
+ })
+
+ menu.ZIndex = scroller.ZIndex
+ menu.Parent = GUI
+ menu.Visible = false
+ menu.Size = UDim2.new(0, new.AbsoluteSize.X, 0, 100);
+ menu.BackgroundColor3 = data.BackgroundColor3 or new.BackgroundColor3
+
+ if data.TextAlignment then
+ selected.TextXAlignment = data.TextAlignment
+ selected.Position = UDim2.fromOffset(30, 0);
+ end
+
+ if data.NoArrow then
+ downImg.Visible = false
+ end
+
+ new:SetSpecial("MenuContainer", menu)
+
+ new.Changed:Connect(function(p)
+ if p == "AbsolutePosition" and menu.Visible then
+ menu.Position = UDim2.fromOffset(new.AbsolutePosition.X, new.AbsolutePosition.Y+new.AbsoluteSize.Y)
+ elseif p == "AbsoluteSize" or p == "Parent" then
+ downImg.Size = UDim2.new(0, new.AbsoluteSize.Y, 1, 0);
+ if data.TextAlignment == "Right" then
+ downImg.Position = UDim2.new(0, 0, 0.5, -(downImg.AbsoluteSize.X/2))
+ selected.Position = UDim2.fromOffset(new.AbsoluteSize.Y, 0);
+ else
+ downImg.Position = UDim2.new(1, -downImg.AbsoluteSize.X, 0.5, -(downImg.AbsoluteSize.X/2))
+ end
+
+ selected.Size = UDim2.new(1, -downImg.AbsoluteSize.X, 1, 0);
+
+ if options and #options <= 6 then
+ menu.Size = UDim2.fromOffset(new.AbsoluteSize.X, 30*#options);
+ else
+ menu.Size = UDim2.fromOffset(new.AbsoluteSize.X, 30*6);
+ scroller:ResizeCanvas(false, true);
+ end
+ end
+ end)
+
+ selected.ZIndex = new.ZIndex
+ downImg.ZIndex = new.ZIndex
+
+ if textProps then
+ for i,v in pairs(textProps) do
+ selected[i] = v
+ end
+ end
+
+ if options then
+ for i,v in pairs(options) do
+ local button = scroller:Add("TextButton", {
+ Text = ` {v}`;
+ Size = UDim2.new(1, -10, 0, 30);
+ Position = UDim2.new(0, 5, 0, 30*(i-1));
+ ZIndex = menu.ZIndex;
+ BackgroundTransparency = 1;
+ OnClick = function()
+ selected.Text = v;
+ onSelect(v, new);
+ menu.Visible = false
+ end
+ })
+
+ if textProps then
+ for i,v in pairs(textProps) do
+ button[i] = v
+ end
+ end
+ end
+
+ if curSelected then
+ selected.Text = curSelected
+ else
+ selected.Text = "No Selection"
+ end
+
+ local function showMenu()
+ menu.Position = UDim2.fromOffset(new.AbsolutePosition.X, new.AbsolutePosition.Y+new.AbsoluteSize.Y)
+ menu.Visible = not menu.Visible
+ end
+
+ selected.MouseButton1Down:Connect(showMenu)
+ downImg.MouseButton1Down:Connect(showMenu)
+ end
+ end
+
+ if class == "TabFrame" then
+ local buttonsTab = {};
+ local buttons = create("ScrollingFrame", nil, new.Buttons)
+ local frames = new.Frames
+ local numTabs = 0
+ local buttonSize = data.ButtonSize or 60
+
+ new.BackgroundTransparency = data.BackgroundTransparency or 1
+ buttons.ZIndex = data.ZIndex or new.ZIndex
+ frames.ZIndex = buttons.ZIndex
+
+ new:SetSpecial("GetTab", function(ignore, name)
+ return frames:FindFirstChild(name)
+ end)
+
+ new:SetSpecial("NewTab", function(ignore, name, data)
+ local data = data or {}
+ --local numChildren = #frames:GetChildren()
+ local nextPos = getNextPos(buttons);
+ local textSize = service.TextService:GetTextSize(data.Text or name, dTextSize, dFont, buttons.AbsoluteSize)
+ local oTextTrans = data.TextTransparency
+ local isOpen = false
+ local disabled = false
+ local tabFrame = create("ScrollingFrame",{
+ Name = name;
+ Size = UDim2.fromScale(1, 1);
+ Position = UDim2.new();
+ BorderSizePixel = 0;
+ BackgroundTransparency = data.FrameTransparency or data.Transparency;
+ BackgroundColor3 = data.Color or dSecondaryBackground;
+ ZIndex = buttons.ZIndex;
+ Visible = false;
+ })
+
+ local tabButton = create("TextButton",{
+ Name = name;
+ Text = data.Text or name;
+ Size = UDim2.new(0, textSize.X+20, 1, 0);
+ ZIndex = buttons.ZIndex;
+ Position = UDim2.new(0, (nextPos.X.Offset > 0 and nextPos.X.Offset+5) or 0, 0, 0);
+ TextColor3 = data.TextColor;
+ BackgroundTransparency = 0.7;
+ TextTransparency = data.TextTransparency;
+ BackgroundColor3 = data.Color or dSecondaryBackground;
+ BorderSizePixel = 0;
+ })
+
+ tabFrame:SetSpecial("FocusTab",function()
+ for i,v in ipairs(buttonsTab) do
+ if isGui(v) then
+ v.BackgroundTransparency = (v:IsDisabled() and 0.9) or 0.7
+ v.TextTransparency = (v:IsDisabled() and 0.9) or 0.7
+ end
+ end
+
+ for i,v in ipairs(frames:GetChildren()) do
+ if isGui(v) then
+ v.Visible = false
+ end
+ end
+
+ tabButton.BackgroundTransparency = data.Transparency or 0
+ tabButton.TextTransparency = data.TextTransparency or 0
+ tabFrame.Visible = true
+
+ if data.OnFocus then
+ data.OnFocus(true)
+ end
+ end)
+
+ if numTabs == 0 then
+ tabFrame.Visible = true
+ tabButton.BackgroundTransparency = data.Transparency or 0
+ end
+
+ tabButton.MouseButton1Down:Connect(function()
+ if not disabled then
+ tabFrame:FocusTab()
+ end
+ end)
+
+ tabButton.Parent = buttons
+ tabFrame.Parent = frames
+ buttons:ResizeCanvas(true, false)
+
+ tabFrame:SetSpecial("Disable", function()
+ disabled = true;
+ tabButton.BackgroundTransparency = 0.9;
+ tabButton.TextTransparency = 0.9
+ end)
+
+ tabFrame:SetSpecial("Enable", function()
+ disabled = false;
+ tabButton.BackgroundTransparency = 0.7;
+ tabButton.TextTransparency = data.TextTransparency or 0;
+ end)
+
+ tabButton:SetSpecial("IsDisabled", function()
+ return disabled;
+ end)
+
+ table.insert(buttonsTab, tabButton);
+
+ numTabs = numTabs+1;
+
+ return tabFrame,tabButton
+ end)
+ end
+
+ if class == "ScrollingFrame" then
+ local genning = false
+ if not data.ScrollBarThickness then
+ data.ScrollBarThickness = dScrollBar
+ end
+
+ new:SetSpecial("GenerateList", function(obj, list, labelProperties, bottom)
+ local list = list or obj;
+ local genHold = {}
+ local entProps = labelProperties or {}
+
+ genning = genHold
+ new:ClearAllChildren()
+
+ new.AutomaticCanvasSize = "Y"
+
+ local layout = service.New("UIListLayout", {
+ Parent = new;
+ Name = "LayoutOrder";
+ FillDirection = data.Layout_FillDirection or "Vertical";
+ VerticalAlignment = data.Layout_VerticalAlignment or "Top";
+ HorizontalAlignment = data.Layout_HorizontalAlignment or "Left";
+ })
+
+ local num = 0
+ for i,v in pairs(list) do
+ local text = v;
+ local desc;
+ local color
+ local richText;
+ local onClick;
+
+ if type(v) == "table" then
+ text = v.Text
+ desc = v.Desc
+ color = v.Color
+ onClick = v.OnClick
+
+ if v.RichTextAllowed or entProps.RichTextAllowed then
+ richText = true
+ end
+ end
+
+ local label
+ if v.TextSelectable or entProps.TextSelectable then
+ label = create("TextBox",{
+ Text = ` {text}`;
+ ToolTip = desc;
+ AutomaticSize = if not entProps.ySize then Enum.AutomaticSize.Y else nil;
+ Size = UDim2.new(1,-5,0,(entProps.ySize or 20));
+ Visible = true;
+ BackgroundTransparency = 1;
+ Font = "Arial";
+ TextSize = 14;
+ TextStrokeTransparency = 0.8;
+ TextXAlignment = "Left";
+ Position = UDim2.new(0,0,0,num*(entProps.ySize or 20));
+ RichText = richText or false;
+ TextEditable = false;
+ ClearTextOnFocus = false;
+ })
+ else
+ label = create(onClick and "TextButton" or "TextLabel",{
+ Text = ` {text}`;
+ ToolTip = desc;
+ AutomaticSize = if not entProps.ySize then Enum.AutomaticSize.Y else nil;
+ Size = UDim2.new(1,-5,0,(entProps.ySize or 20));
+ Visible = true;
+ BackgroundTransparency = 1;
+ Font = "Arial";
+ TextSize = 14;
+ TextStrokeTransparency = 0.8;
+ TextXAlignment = "Left";
+ Position = UDim2.new(0,0,0,num*(entProps.ySize or 20));
+ RichText = richText or false;
+ OnClick = onClick;
+ })
+ end
+
+ if color then
+ label.TextColor3 = color
+ end
+
+ if labelProperties then
+ for i,v in pairs(entProps) do
+ if checkProperty(label, i) then
+ label[i] = v
+ end
+ end
+ end
+
+ if genning == genHold then
+ label.Parent = new;
+ else
+ label:Destroy()
+ break
+ end
+
+ num = num+1
+
+ if data.Delay then
+ if type(data.Delay) == "number" then
+ wait(data.Delay)
+ elseif i%100 == 0 then
+ wait(0.1)
+ end
+ end
+ end
+
+ --new:ResizeCanvas(false, true, false, bottom, 5, 5, 50)
+ if bottom then
+ new.CanvasPosition = Vector2.new(0, layout.AbsoluteContentSize.Y);
+ end
+
+ genning = nil
+ end)
+
+ new:SetSpecial("ResizeCanvas", function(ignore, onX, onY, xMax, yMax, xPadding, yPadding, modBreak)
+ local xPadding,yPadding = data.xPadding or 5, data.yPadding or 5
+ local newY, newX = 0,0
+
+ if not onX and not onY then onX = false onY = true end
+ for i,v in ipairs(new:GetChildren()) do
+ if v:IsA("GuiObject") then
+ if onY then
+ v.Size = UDim2.new(v.Size.X.Scale, v.Size.X.Offset, 0, v.AbsoluteSize.Y)
+ v.Position = UDim2.new(v.Position.X.Scale, v.Position.X.Offset, 0, v.AbsolutePosition.Y-new.AbsolutePosition.Y)
+ end
+
+ if onX then
+ v.Size = UDim2.new(0, v.AbsoluteSize.X, v.Size.Y.Scale, v.Size.Y.Offset)
+ v.Position = UDim2.new(0, v.AbsolutePosition.X-new.AbsolutePosition.X, v.Position.Y.Scale, v.Position.Y.Offset)
+ end
+
+ local yLower = v.Position.Y.Offset + v.Size.Y.Offset
+ local xLower = v.Position.X.Offset + v.Size.X.Offset
+ newY = math.max(newY, yLower)
+ newX = math.max(newX, xLower)
+ if modBreak then
+ if i%modBreak == 0 then
+ wait(1/60)
+ end
+ end
+ end
+ end
+
+ if onY then
+ new.CanvasSize = UDim2.new(new.CanvasSize.X.Scale, new.CanvasSize.X.Offset, 0, newY+yPadding)
+ end
+
+ if onX then
+ new.CanvasSize = UDim2.new(0, newX + xPadding, new.CanvasSize.Y.Scale, new.CanvasSize.Y.Offset)
+ end
+
+ if xMax then
+ new.CanvasPosition = Vector2.new((newX + xPadding)-new.AbsoluteSize.X, new.CanvasPosition.Y)
+ end
+
+ if yMax then
+ new.CanvasPosition = Vector2.new(new.CanvasPosition.X, (newY+yPadding)-new.AbsoluteSize.Y)
+ end
+ end)
+
+ if data.List then new:GenerateList(data.List) data.List = nil end
+ end
+
+ LoadChildren(new, data.Content or data.Children)
+
+ data.Children = nil
+ data.Content = nil
+
+ for i,v in pairs(data) do
+ if checkProperty(new, i) then
+ new[i] = v
+ end
+ end
+
+ new.Parent = parent
+
+ return apiIfy(new, data, class),data
+ end
+
+ function apiIfy(gui, data, class)
+ local newGui = service.Wrap(gui)
+ gui:SetSpecial("Object", gui)
+ gui:SetSpecial("SetPosition", function(ignore, newPos) gui.Position = newPos end)
+ gui:SetSpecial("SetSize", function(ingore, newSize) gui.Size = newSize end)
+ gui:SetSpecial("Add", function(ignore, class, data)
+ if not data then data = class class = ignore end
+ local new = create(class,data);
+ new.Parent = gui;
+ return apiIfy(new, data, class)
+ end)
+
+ gui:SetSpecial("Copy", function(ignore, class, gotData)
+ local newData = {}
+ local new
+
+ for i,v in pairs(data) do
+ newData[i] = v
+ end
+
+ for i,v in pairs(gotData) do
+ newData[i] = v
+ end
+
+ new = create(class or data.Class or gui.ClassName, newData);
+ new.Parent = gotData.Parent or gui.Parent;
+ return apiIfy(new, data, class)
+ end)
+
+ return newGui
+ end
+
+ function doClose()
+ if not isClosed then
+ isClosed = true
+
+ if onClose then
+ local r,e = pcall(onClose)
+ if e then
+ warn(e)
+ end
+ end
+
+ gTable:Destroy()
+ end
+ end
+
+ function isVisible()
+ return Main.Visible
+ end
+
+ local hideLabel = Hide:FindFirstChild("TextLabel")
+ function doHide(doHide)
+ local origLH = Hide.LineHeight
+ if doHide or (doHide == nil and Main.Visible) then
+ dragSize = Drag.Size
+ Main.Visible = false
+ Drag.BackgroundTransparency = Main.BackgroundTransparency
+ Drag.BackgroundColor3 = Main.BackgroundColor3
+ -- Check if user wants to keep width on minimize
+ local keepWidth = client and client.Variables and client.Variables.KeepWindowWidthOnMinimize
+ local currentWidth = Drag.Size.X.Offset
+ local newWidth = keepWidth and math.max(currentWidth, MinSize[1]) or 200
+ Drag.Size = UDim2.new(0, newWidth, Drag.Size.Y.Scale, Drag.Size.Y.Offset)
+
+ if hideLabel then
+ hideLabel.Text = "+"
+ else
+ Hide.Text = "+"
+ end
+
+ Hide.LineHeight = origLH
+ gTable.Minimized = true
+ elseif doHide == false or (doHide == nil and not Main.Visible) then
+ Main.Visible = true
+ Drag.BackgroundTransparency = 1
+ Drag.Size = dragSize or Drag.Size
+
+ if hideLabel then
+ hideLabel.Text = "-"
+ else
+ Hide.Text = "-"
+ end
+
+ Hide.LineHeight = origLH
+ gTable.Minimized = false
+ end
+
+ if onMinimize then
+ onMinimize(Main.Visible)
+ end
+
+ if Walls then
+ wallPosition()
+ end
+ end
+
+ function isInFrame(x, y, frame)
+ if x > frame.AbsolutePosition.X and x < (frame.AbsolutePosition.X+frame.AbsoluteSize.X) and y > frame.AbsolutePosition.Y and y < (frame.AbsolutePosition.Y+frame.AbsoluteSize.Y) then
+ return true
+ else
+ return false
+ end
+ end
+
+ function wallPosition()
+ if gTable.Active then
+ local x,y = Drag.AbsolutePosition.X, Drag.AbsolutePosition.Y
+ local abx, gx, gy = Drag.AbsoluteSize.X, GUI.AbsoluteSize.X, GUI.AbsoluteSize.Y
+ local ySize = (Main.Visible and Main.AbsoluteSize.Y) or Drag.AbsoluteSize.Y
+
+ if x < 0 then
+ Drag.Position = UDim2.new(0, 0, Drag.Position.Y.Scale, Drag.Position.Y.Offset)
+ end
+
+ if y < 0 then
+ Drag.Position = UDim2.new(Drag.Position.X.Scale, Drag.Position.X.Offset, 0, 0)
+ end
+
+ if x + abx > gx then
+ Drag.Position = UDim2.new(0, GUI.AbsoluteSize.X - Drag.AbsoluteSize.X, Drag.Position.Y.Scale, Drag.Position.Y.Offset)
+ end
+
+ if y + ySize > gy then
+ Drag.Position = UDim2.new(Drag.Position.X.Scale, Drag.Position.X.Offset, 0, GUI.AbsoluteSize.Y - ySize)
+ end
+ end
+ end
+
+ function setSize(newSize)
+ if newSize and type(newSize) == "table" then
+ if newSize[1] < 50 then newSize[1] = 50 end
+ if newSize[2] < 50 then newSize[2] = 50 end
+
+ Drag.Size = UDim2.new(0,newSize[1],Drag.Size.Y.Scale,Drag.Size.Y.Offset)
+ Main.Size = UDim2.new(1,0,0,newSize[2])
+ end
+ end
+
+ function setPosition(newPos)
+ if newPos and typeof(newPos) == "UDim2" then
+ Drag.Position = newPos
+ elseif newPos and type(newPos) == "table" then
+ Drag.Position = UDim2.new(0, newPos[1], 0, newPos[2])
+ elseif Size and not newPos then
+ Drag.Position = UDim2.new(0.5, -Drag.AbsoluteSize.X/2, 0.5, -Main.AbsoluteSize.Y/2)
+ end
+ end
+
+ function setMinSize(Table)
+ if Table and type(Table) == "table" then
+ MinSize = Table
+ end
+ end
+
+ function setMaxSize(Table)
+ if Table and type(Table) == "table" then
+ MaxSize = Table
+ end
+ end
+
+ if Name then
+ gTable.Name = Name
+ if data.AllowMultiple ~= nil and data.AllowMultiple == false then
+ local found, num = client.UI.Get(Name, GUI, true)
+ if found then
+ doClose()
+ return nil
+ end
+ end
+ end
+
+ if Size then
+ setSize(Size)
+ end
+
+ if Position then
+ setPosition(Position)
+ end
+
+ if Title then
+ Titlef.Text = Title
+ end
+
+ if CanKeepAlive or not ResetOnSpawn then
+ gTable.CanKeepAlive = true
+ GUI.ResetOnSpawn = false
+ elseif ResetOnSpawn then
+ gTable.CanKeepAlive = false
+ GUI.ResetOnSpawn = true
+ end
+
+ if Icon then
+ Iconf.Visible = true
+ Iconf.Image = Icon
+ Iconf.Size = UDim2.new(0, 16, 0, 16)
+ Iconf.Position = UDim2.new(0, 6, 0, 5)
+ Iconf.ImageTransparency = 0
+ end
+
+ if CanvasSize then
+ ScrollFrame.CanvasSize = CanvasSize
+ end
+
+ if noClose then
+ Close.Visible = false
+ Refresh.Position = Hide.Position
+ Hide.Position = Close.Position
+ end
+
+ if noHide then
+ Hide.Visible = false
+ Refresh.Position = Hide.Position
+ end
+
+ if Walls then
+ Drag.DragStopped:Connect(function()
+ wallPosition()
+ end)
+ end
+
+ if onRefresh then
+ local debounce = false
+ function DoRefresh()
+ if not Refreshing then
+ local done = false
+ Refreshing = true
+
+ spawn(function()
+ while gTable.Active and not done do
+ for i = 0,180,10 do
+ rSpinner.Rotation = -i
+ wait(1/60)
+ end
+ end
+ end)
+
+ onRefresh()
+ wait(1)
+ done = true
+ Refreshing = false
+ end
+ end
+
+ Refresh.MouseButton1Down:Connect(function()
+ if not debounce then
+ debounce = true
+ DoRefresh()
+ debounce = false
+ end
+ end)
+
+ Titlef.Size = UDim2.new(1, -130, Titlef.Size.Y.Scale, Titlef.Size.Y.Offset)
+ else
+ Refresh.Visible = false
+ end
+
+ if iconClicked then
+ Iconf.MouseButton1Down(function()
+ iconClicked(data, GUI, Iconf)
+ end)
+ end
+
+ if Menu then
+ data.Menu.Text = ""
+ data.Menu.Parent = Main
+ data.Menu.Size = UDim2.new(1,-10,0,25)
+ data.Menu.Position = UDim2.new(0,5,0,25)
+ ScrollFrame.Size = UDim2.new(1,-10,1,-55)
+ ScrollFrame.Position = UDim2.new(0,5,0,50)
+ data.Menu.BackgroundColor3 = Color3.fromRGB(216, 216, 216)
+ data.Menu.BorderSizePixel = 0
+ create("TextLabel",data.Menu)
+ end
+
+ if not SizeLocked then
+ local startXPos = Drag.AbsolutePosition.X
+ local startYPos = Drag.AbsolutePosition.Y
+ local startXSize = Drag.AbsoluteSize.X
+ local startYSize = Drag.AbsoluteSize.Y
+ local vars = client.Variables
+ local newIcon
+ local inFrame
+ local ReallyInFrame
+
+ local function readify(obj)
+ obj.MouseEnter:Connect(function()
+ ReallyInFrame = obj
+ end)
+
+ obj.MouseLeave:Connect(function()
+ if ReallyInFrame == obj then
+ ReallyInFrame = nil
+ end
+ end)
+ end
+
+ --[[
+ readify(Drag)
+ readify(ScrollFrame)
+ readify(TopRight)
+ readify(TopLeft)
+ readify(RightCorner)
+ readify(LeftCorner)
+ readify(RightSide)
+ readify(LeftSide)
+ readify(Bottom)
+ readify(Top)
+ --]]
+
+ function checkMouse(x, y) --// Update later to remove frame by frame pos checking
+ if gTable.Active and Main.Visible then
+ if isInFrame(x, y, Drag) or isInFrame(x, y, ScrollFrame) then
+ inFrame = nil
+ newIcon = nil
+ elseif isInFrame(x, y, TopRight) then
+ inFrame = "TopRight"
+ newIcon = MouseIcons.TopRight
+ elseif isInFrame(x, y, TopLeft) then
+ inFrame = "TopLeft"
+ newIcon = MouseIcons.TopLeft
+ elseif isInFrame(x, y, RightCorner) then
+ inFrame = "RightCorner"
+ newIcon = MouseIcons.RightCorner
+ elseif isInFrame(x, y, LeftCorner) then
+ inFrame = "LeftCorner"
+ newIcon = MouseIcons.LeftCorner
+ elseif isInFrame(x, y, RightSide) then
+ inFrame = "RightSide"
+ newIcon = MouseIcons.Horizontal
+ elseif isInFrame(x, y, LeftSide) then
+ inFrame = "LeftSide"
+ newIcon = MouseIcons.Horizontal
+ elseif isInFrame(x, y, Bottom) then
+ inFrame = "Bottom"
+ newIcon = MouseIcons.Vertical
+ elseif isInFrame(x, y, Top) then
+ inFrame = "Top"
+ newIcon = MouseIcons.Vertical
+ else
+ inFrame = nil
+ newIcon = nil
+ end
+ else
+ inFrame = nil
+ end
+
+ if (not client.Variables.MouseLockedBy) or client.Variables.MouseLockedBy == gTable then
+ if inFrame and newIcon then
+ Mouse.Icon = newIcon
+ client.Variables.MouseLockedBy = gTable
+ elseif client.Variables.MouseLockedBy == gTable then
+ Mouse.Icon = curIcon
+ client.Variables.MouseLockedBy = nil
+ end
+ end
+ end
+
+ local function inputStart(x, y)
+ checkMouse(x, y)
+ if gTable.Active and inFrame and not Resizing and not isInFrame(x, y, ScrollFrame) and not isInFrame(x, y, Drag) then
+ Resizing = inFrame
+ startXPos = Drag.AbsolutePosition.X
+ startYPos = Drag.AbsolutePosition.Y
+ startXSize = Drag.AbsoluteSize.X
+ startYSize = Main.AbsoluteSize.Y
+ end
+ end
+
+ local function inputEnd()
+ if gTable.Active then
+ if Resizing and onResize then
+ onResize(UDim2.new(Drag.Size.X.Scale, Drag.Size.X.Offset, Main.Size.Y.Scale, Main.Size.Y.Offset))
+ end
+
+ Resizing = nil
+ Mouse.Icon = curIcon
+ --DragEnabled = true
+ --if Walls then
+ -- wallPosition()
+ --end
+ end
+ end
+
+ local function inputMoved(x, y)
+ if gTable.Active then
+ if Mouse.Icon ~= MouseIcons.TopRight and Mouse.Icon ~= MouseIcons.TopLeft and Mouse.Icon ~= MouseIcons.RightCorner and Mouse.Icon ~= MouseIcons.LeftCorner and Mouse.Icon ~= MouseIcons.Horizontal and Mouse.Icon ~= MouseIcons.Vertical then
+ curIcon = Mouse.Icon
+ end
+
+ if Resizing then
+ local moveX = false
+ local moveY = false
+ local newPos = Drag.Position
+ local xPos, yPos = x, y
+ local newX, newY = startXSize, startYSize
+
+ --DragEnabled = false
+
+ if Resizing == "TopRight" then
+ newX = (xPos - startXPos) + 3
+ newY = (startYPos - yPos) + startYSize -1
+ moveY = true
+ elseif Resizing == "TopLeft" then
+ newX = (startXPos - xPos) + startXSize -1
+ newY = (startYPos - yPos) + startYSize -1
+ moveY = true
+ moveX = true
+ elseif Resizing == "RightCorner" then
+ newX = (xPos - startXPos) + 3
+ newY = (yPos - startYPos) + 3
+ elseif Resizing == "LeftCorner" then
+ newX = (startXPos - xPos) + startXSize + 3
+ newY = (yPos - startYPos) + 3
+ moveX = true
+ elseif Resizing == "LeftSide" then
+ newX = (startXPos - xPos) + startXSize + 3
+ newY = startYSize
+ moveX = true
+ elseif Resizing == "RightSide" then
+ newX = (xPos - startXPos) + 3
+ newY = startYSize
+ elseif Resizing == "Bottom" then
+ newX = startXSize
+ newY = (yPos - startYPos) + 3
+ elseif Resizing == "Top" then
+ newX = startXSize
+ newY = (startYPos - yPos) + startYSize - 1
+ moveY = true
+ end
+
+ if newX < MinSize[1] then newX = MinSize[1] end
+ if newY < MinSize[2] then newY = MinSize[2] end
+ if newX > MaxSize[1] then newX = MaxSize[1] end
+ if newY > MaxSize[2] then newY = MaxSize[2] end
+
+ if moveX then
+ newPos = UDim2.new(0, (startXPos+startXSize)-newX, newPos.Y.Scale, newPos.Y.Offset)
+ end
+
+ if moveY then
+ newPos = UDim2.new(newPos.X.Scale, newPos.X.Offset, 0, (startYPos+startYSize)-newY)
+ end
+
+ Drag.Position = newPos
+ Drag.Size = UDim2.new(0, newX, Drag.Size.Y.Scale, Drag.Size.Y.Offset)
+ Main.Size = UDim2.new(Main.Size.X.Scale, Main.Size.X.Offset, 0, newY)
+
+ if not Titlef.TextFits then
+ Titlef.Visible = false
+ else
+ Titlef.Visible = true
+ end
+ else
+ checkMouse(x, y)
+ end
+ end
+ end
+
+ Event(InputService.InputBegan, function(input, gameHandled)
+ if not gameHandled and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then
+ local Position = input.Position
+ inputStart(Position.X, Position.Y)
+ end
+ end)
+
+ Event(InputService.InputChanged, function(input, gameHandled)
+ if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
+ local Position = input.Position
+ inputMoved(Position.X, Position.Y)
+ end
+ end)
+
+ Event(InputService.InputEnded, function(input, gameHandled)
+ if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
+ inputEnd()
+ end
+ end)
+
+ --[[Event(Mouse.Button1Down, function()
+ if gTable.Active and inFrame and not Resizing and not isInFrame(Mouse.X, Mouse.Y, ScrollFrame) and not isInFrame(Mouse.X, Mouse.Y, Drag) then
+ Resizing = inFrame
+ startXPos = Drag.AbsolutePosition.X
+ startYPos = Drag.AbsolutePosition.Y
+ startXSize = Drag.AbsoluteSize.X
+ startYSize = Main.AbsoluteSize.Y
+ checkMouse()
+ end
+ end)
+
+ Event(Mouse.Button1Up, function()
+ if gTable.Active then
+ if Resizing and onResize then
+ onResize(UDim2.new(Drag.Size.X.Scale, Drag.Size.X.Offset, Main.Size.Y.Scale, Main.Size.Y.Offset))
+ end
+
+ Resizing = nil
+ Mouse.Icon = curIcon
+ --if Walls then
+ -- wallPosition()
+ --end
+ end
+ end)--]]
+ else
+ LeftSizeIcon.Visible = false
+ RightSizeIcon.Visible = false
+ end
+
+
+ Close.MouseButton1Down:Connect(doClose)
+ Hide.MouseButton1Down:Connect(function() doHide() end)
+ gTable.CustomDestroy = function()
+ if client.Variables.MouseLockedBy == gTable then
+ Mouse.Icon = curIcon
+ client.Variables.MouseLockedBy = nil
+ end
+
+ if not isClosed then
+ isClosed = true
+ if onClose then
+ onClose()
+ end
+ end
+
+ service.UnWrap(GUI):Destroy()
+ end
+
+ for i,child in ipairs(GUI:GetChildren()) do
+ if child.Name ~= "Desc" and child.Name ~= "Drag" then
+ specialInsts[child.Name] = child
+ child.Parent = nil
+ end
+ end
+
+ --// Drag & DisplayOrder Handler
+ do
+ local windowValue = Instance.new("BoolValue", GUI)
+ local dragDragging = false
+ local dragOffset
+ local inFrame
+
+ windowValue.Name = "__ADONIS_WINDOW"
+
+ Event(Main.InputBegan, function(input)
+ if gTable.Active and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then
+ BringToFront()
+ end
+ end)
+
+ Event(Drag.InputBegan, function(input)
+ if gTable.Active then
+ inFrame = true
+
+ if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
+ BringToFront()
+ end
+ end
+ end)
+
+ Event(Drag.InputChanged, function(input)
+ if gTable.Active then
+ inFrame = true
+ end
+ end)
+
+ Event(Drag.InputEnded, function(input)
+ inFrame = false
+ end)
+
+ Event(InputService.InputBegan, function(input)
+ if inFrame and GUI.DisplayOrder == 101 and not dragDragging and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then--isInFrame(input.Position.X, input.Position.Y, object) then
+ if not noDrag then
+ dragDragging = true
+ BringToFront()
+ dragOffset = Vector2.new(Drag.AbsolutePosition.X - input.Position.X, Drag.AbsolutePosition.Y - input.Position.Y)
+ end
+ end
+ end)
+
+ Event(InputService.InputChanged, function(input)
+ if dragDragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
+ Drag.Position = UDim2.fromOffset(dragOffset.X + input.Position.X, dragOffset.Y + input.Position.Y)
+ end
+ end)
+
+ Event(InputService.InputEnded, function(input)
+ if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
+ dragDragging = false
+ end
+ end)
+ end
+
+ --// Finishing up
+ local api = apiIfy(ScrollFrame, data)
+ local meta = api:GetMetatable()
+ local oldNewIndex = meta.__newindex
+ local oldIndex = meta.__index
+
+ create("ScrollingFrame", nil, ScrollFrame)
+ LoadChildren(api, Content)
+
+ api:SetSpecial("gTable", gTable)
+ api:SetSpecial("Window", GUI)
+ api:SetSpecial("Main", Main)
+ api:SetSpecial("Title", Titlef)
+ api:SetSpecial("Dragger", Drag)
+ api:SetSpecial("Destroy", doClose)
+ api:SetSpecial("Close", doClose)
+ api:SetSpecial("Object", ScrollFrame)
+ api:SetSpecial("Refresh", DoRefresh)
+ api:SetSpecial("AddTitleButton", function(ignore, data) if type(ignore) == "table" and not data then data = ignore end return addTitleButton(data) end)
+ api:SetSpecial("Ready", function() if onReady then onReady() end gTable.Ready() BringToFront() end)
+ api:SetSpecial("BindEvent", function(ignore, ...) return Event(...) end)
+ api:SetSpecial("Hide", function(ignore, hide) doHide(hide) end)
+ api:SetSpecial("SetTitle", function(ignore, newTitle) Titlef.Text = newTitle end)
+ api:SetSpecial("SetPosition", function(ignore, newPos) setPosition(newPos) end)
+ api:SetSpecial("SetSize", function(ignore, newSize) setSize(newSize) end)
+ api:SetSpecial("SetMinSize",function(ignore, Table) setMinSize(Table) end)
+ api:SetSpecial("SetMaxSize",function(ignore, Table) setMaxSize(Table) end)
+ api:SetSpecial("GetPosition", function() return Drag.AbsolutePosition end)
+ api:SetSpecial("GetSize", function() return Main.AbsoluteSize end)
+ api:SetSpecial("IsVisible", isVisible)
+ api:SetSpecial("IsClosed", isClosed)
+
+ meta.__index = function(tab, ind)
+ if ind == "IsVisible" then
+ return isVisible()
+ elseif ind == "Closed" then
+ return isClosed
+ else
+ return oldIndex(tab, ind)
+ end
+ end
+
+ setSize(Size)
+ setPosition(Position)
+
+ if Ready then
+ gTable:Ready()
+ BringToFront()
+ end
+
+ return api,GUI
+end]]>
+ -1
+
+
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.639215708
+ 0.635294139
+ 0.647058845
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ ColorEntry
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 0
+ 0
+ 60
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -10
+ 0
+ 20
+
+ 0
+ -1
+
+ Color:
+
+ 1
+ 1
+ 1
+
+ 0
+ true
+ 24
+
+ 0
+ 0
+ 0
+
+ 0.800000012
+ 0
+ 0
+ true
+ 0
+ 0
+ false
+ 2
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 0.270588249
+ 0.24313727
+ 0.545098066
+
+ 0
+
+ 1
+ 1
+ 1
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Button
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -50
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 50
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 18
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ false
+ 1
+ 1
+ true
+ 2
+
+
+ -
+
+
+ 0
+ false
+ Desc
+ -1
+
+ TestDesc
+
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.639215708
+ 0.635294139
+ 0.647058845
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ BooleanEntry
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 0
+ 0
+ 20
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -10
+ 0
+ 20
+
+ 0
+ -1
+
+ Boolean:
+
+ 1
+ 1
+ 1
+
+ 0
+ true
+ 24
+
+ 0
+ 0
+ 0
+
+ 0.800000012
+ -7.30156913e-08
+ 0
+ true
+ 0
+ 0
+ false
+ 2
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Button
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -100
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 100
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ Disabled
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 18
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ false
+ 1
+ 1
+ true
+ 2
+
+
+ -
+
+
+ 0
+ false
+ Desc
+ -1
+
+ TestDesc
+
+
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 0.121568635
+ 0.121568635
+ 0.121568635
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/LegacyArial.json
+ 400
+
+ rbxasset://fonts/Arimo-Regular.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Drag
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 400
+ 0.5
+ -100
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 400
+ 0
+ 25
+
+ 0
+ -1
+ 0
+
+
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ false
+ 8
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ false
+ 2
+ 1
+ true
+ 1
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 0
+ 0
+ 0
+
+ 0.5
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 700
+
+ rbxasset://fonts/arialbd.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Refresh
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -97
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 30
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 12
+
+ 0
+ 0
+ 0
+
+ 0.899999976
+ 0
+ 0
+ false
+ 2
+ 1
+ true
+ 2
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+ rbxassetid://69395121
+
+ 1
+ 1
+ 1
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 0.100000001
+ true
+ 0
+ Spinner
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 8
+ 0
+ 3
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 14
+ 0
+ 14
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+
+
+ 1
+ 0
+ 1
+ 0
+
+ true
+ 10
+
+
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxasset://textures/ui/Menu/Hamburger.png
+
+ 1
+ 1
+ 1
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 0.300000012
+ true
+ 0
+ false
+ Icon
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 6
+ 0
+ 6
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 14
+ 0
+ 14
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ true
+ 2
+
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 0
+ 0
+ 0
+
+ 0.5
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 700
+
+ rbxasset://fonts/arialbd.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Hide
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -66
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 30
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ -
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 12
+
+ 0
+ 0
+ 0
+
+ 0.899999976
+ 0
+ 0
+ false
+ 2
+ 1
+ true
+ 2
+
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 0.764705956
+ 0.129411772
+ 0.137254909
+
+ 0.25
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/ComicNeueAngular.json
+ 400
+
+ rbxasset://fonts/ComicNeue-Angular-Bold.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Close
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -35
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 30
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ x
+
+ 0.862745166
+ 0.862745166
+ 0.862745166
+
+ 0
+ false
+ 18
+
+ 0
+ 0
+ 0
+
+ 0.899999976
+ 0
+ 0
+ true
+ 2
+ 0
+ true
+ 2
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/ComicNeueAngular.json
+ 400
+
+ rbxasset://fonts/ComicNeue-Angular-Bold.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ TextLabel
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0.5
+ 0
+ 0.5
+ -1
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ -1
+
+ x
+
+ 0.870588303
+ 0.870588303
+ 0.870588303
+
+ 0
+ false
+ 22
+
+ 0
+ 0
+ 0
+
+ 0.899999976
+ 0
+ 0
+ true
+ 2
+ 1
+ true
+ 10
+
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.101960793
+ 0.113725498
+ 0.164705887
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ true
+ false
+ false
+
+ rbxasset://fonts/families/SourceSansPro.json
+ 300
+
+ rbxasset://fonts/SourceSansPro-Light.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ Title
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 26
+ 0
+ 0
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -100
+ 1
+ -3
+
+ 0
+ -1
+
+ Window Title
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 18
+
+ 0.313725501
+ 0.313725501
+ 0.313725501
+
+ 0.899999976
+ 0
+ 0
+ true
+ 0
+ 1
+ true
+ 9
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.121568635
+ 0.121568635
+ 0.121568635
+
+ 0.300000012
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+ true
+ 0
+ Main
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 0
+ 0
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ 0
+ 0
+ 230
+
+ 0
+ -1
+ 0
+
+ true
+ 1
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 1
+ 0.835294187
+ 0
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ Bottom
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 20
+ 1
+ -5
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -40
+ 0
+ 10
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 0.184313729
+ 0.427451015
+ 1
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ RightSide
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 1
+ -5
+ 0
+ 20
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 10
+ 1
+ -40
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.454901993
+ 0.454901993
+ 0.454901993
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 0.5
+ true
+ 0
+ RightResizeIcon
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 1
+ -20
+ 1
+ -20
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 20
+ 0
+ 20
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.454901993
+ 0.454901993
+ 0.454901993
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 0.5
+ true
+ 0
+ LeftResizeIcon
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 1
+ -20
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 20
+ 0
+ 20
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 0.184313729
+ 0.427451015
+ 1
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ LeftSide
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ -5
+ 0
+ 20
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 10
+ 1
+ -40
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 1
+ 0
+ 0
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ RightCorner
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 1
+ -20
+ 1
+ -20
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 25
+ 0
+ 25
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 1
+ 0.215686291
+ 0.988235354
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ Top
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 20
+ 0
+ -5
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -40
+ 0
+ 10
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 1
+ 0.180392161
+ 0.192156881
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ LeftCorner
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ -5
+ 1
+ -20
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 25
+ 0
+ 25
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ false
+ 0
+ 0
+
+ 0.0862745121
+ 0.0862745121
+ 0.0862745121
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ http://roblox.com/asset?id=158348114
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ true
+ false
+ false
+ 0
+ 0
+ true
+ 0
+ http://roblox.com/asset?id=158348114
+ ScrollingFrame
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 5
+ 0
+ 25
+
+ [null]
+ 0
+
+ 1
+ 1
+ 1
+
+ 0
+ 5
+ 2
+ true
+ true
+ 0
+ 0
+ 0
+ 0
+ true
+ [null]
+ 0
+
+ 1
+ -10
+ 1
+ -30
+
+ 0
+ -1
+
+ http://roblox.com/asset?id=158348114
+ 0
+ 0
+ true
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 1
+ 0.180392161
+ 0.192156881
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ TopLeft
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ -5
+ 0
+ -5
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 25
+ 0
+ 25
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ false
+ 0
+
+ 1
+ 0
+ 0
+
+ 0
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
[null]
+
+ rbxassetid://334991942
+
+ 0.647058845
+ 0.647058845
+ 0.647058845
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+ 1
+ true
+ 0
+ false
+ TopRight
+ [null]
+ [null]
+ [null]
+ [null]
+
+ 1
+ -20
+ 0
+ -5
+
+ [null]
+
+ 0
+ [null]
+ 0
+ 0
+ false
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 25
+ 0
+ 25
+
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 1
+ -1
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ false
+ 1
+
+
+
+
+ -
+
+
+ 0
+ false
+ Check
+ -1
+
+ true
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.274509817
+ 0.274509817
+ 0.274509817
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+ true
+ 0
+ TabFrame
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 5
+ 0
+ 5
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -10
+ 1
+ -10
+
+ 0
+ -1
+ 0
+
+ false
+ 1
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+ 0
+
+ 0.192156881
+ 0.192156881
+ 0.192156881
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ rbxasset://textures/ui/Scroll/scroll-middle.png
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+ false
+ false
+ false
+ 0
+ 0
+ true
+ 0
+ rbxasset://textures/ui/Scroll/scroll-middle.png
+ Buttons
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 0
+ 0
+
+ [null]
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+ 3
+ 1
+ true
+ true
+ 0
+ 0
+ 0
+ 0
+ true
+ [null]
+ 0
+
+ 1
+ 0
+ 0
+ 25
+
+ 0
+ -1
+
+ rbxasset://textures/ui/Scroll/scroll-middle.png
+ 0
+ 0
+ true
+ 1
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.192156881
+ 0.192156881
+ 0.192156881
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+ true
+ 0
+ Frames
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 0
+ 25
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ 0
+ 1
+ -25
+
+ 0
+ -1
+ 0
+
+ true
+ 1
+
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.639215708
+ 0.635294139
+ 0.647058845
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ ButtonEntry
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 0
+ 0
+ 20
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -10
+ 0
+ 20
+
+ 0
+ -1
+
+ Button:
+
+ 1
+ 1
+ 1
+
+ 0
+ true
+ 24
+
+ 0
+ 0
+ 0
+
+ 0.800000012
+ -7.30156913e-08
+ 0
+ true
+ 0
+ 0
+ false
+ 2
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Button
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -100
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 100
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ Open
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 18
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ false
+ 1
+ 1
+ true
+ 2
+
+
+ -
+
+
+ 0
+ false
+ Desc
+ -1
+
+ TestDesc
+
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+ true
+ 0
+ Entry
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 0
+ 0
+
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -5
+ 0
+ 15
+
+ 0
+ -1
+ 0
+
+ false
+ 2
+
+ -
+
+
+ 0
+ false
+ Desc
+ -1
+
+ TestDesc
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.541176498
+ 0.53725493
+ 0.545098066
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ true
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ Text
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 5
+ 0
+ 0
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -15
+ 1
+ 0
+
+ 0
+ -1
+
+ The quick brown fox jumps over the lazy dog
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 14
+
+ 0
+ 0
+ 0
+
+ 0.800000012
+ -7.30156913e-08
+ 0
+ false
+ 0
+ 2
+ true
+ 2
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.541176498
+ 0.53725493
+ 0.545098066
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/SourceSansPro.json
+ 400
+
+ rbxasset://fonts/SourceSansPro-Regular.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ Dots
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -10
+ 0
+ 0
+
+ false
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 10
+ 1
+ 0
+
+ 0
+ -1
+
+ ..
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 14
+
+ 0
+ 0
+ 0
+
+ 0.800000012
+ -7.30156913e-08
+ 0
+ false
+ 0
+ 2
+ false
+ 2
+
+
+
+ -
+
+ true
+
+ 0
+ 0
+
+
+ true
+ false
+ 0
+
+ 1
+ 1
+ 1
+
+ 1
+
+ 0.105882362
+ 0.164705887
+ 0.207843155
+
+ 0
+ 0
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/Arial.json
+ 400
+
+ rbxasset://fonts/arial.ttf
+
+
[null]
+ true
+ 0
+ 1
+
+
+ -1
+ false
+ Boolean
+ [null]
+ [null]
+ [null]
+ [null]
+
+
+ 1
+ -100
+ 0
+ 0
+
+ [null]
+ false
+ [null]
+ 0
+ true
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 100
+ 0
+ 20
+
+ 0
+ -1
+ 0
+
+ Disabled
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 18
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ false
+ 2
+ 1
+ true
+ 2
+
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0.227450997
+ 0.227450997
+ 0.227450997
+
+ 0
+
+ 0.325490206
+ 0.325490206
+ 0.325490206
+
+ 0
+ 2
+ 0
+ false
+ false
+ false
+ true
+ 0
+ Desc
+
[null]
+ [null]
+ [null]
+ [null]
+
+ 0
+ 0
+ 0
+ 0
+
+ [null]
+ 0
+ true
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 0
+ 110
+ 0
+ 25
+
+ 0
+ -1
+ 0
+
+ false
+ 999999
+
+ -
+
+ false
+
+ 0
+ 0
+
+
+ false
+ 0
+
+ 0
+ 0
+ 0
+
+ 1
+
+ 0.196078449
+ 0.196078449
+ 0.196078449
+
+ 0
+ 1
+ 0
+ false
+ false
+ false
+
+ rbxasset://fonts/families/SourceSansPro.json
+ 400
+
+ rbxasset://fonts/SourceSansPro-Regular.ttf
+
+ true
+ 0
+ 1
+
+
+ -1
+ Label
+
[null]
+ [null]
+ [null]
+ [null]
+
+
+ 0
+ 5
+ 0
+ 5
+
+ true
+ [null]
+ 0
+ false
+ 0
+ 0
+ 0
+ 0
+ false
+ [null]
+ 0
+
+ 1
+ -10
+ 1
+ -10
+
+ 0
+ -1
+
+ Test Desciption
+
+ 1
+ 1
+ 1
+
+ 0
+ false
+ 18
+
+ 0
+ 0
+ 0
+
+ 1
+ 0
+ 0
+ true
+ 0
+ 0
+ true
+ 999999
+
+
+ -
+
+
+ 0
+
+
0
+ 8
+
+ false
+ UICorner
+ -1
+
+
+
+
+
+
diff --git a/MainModule/Server/Commands/Fun.luau b/MainModule/Server/Commands/Fun.luau
index 4162454a35..ba0c67f172 100644
--- a/MainModule/Server/Commands/Fun.luau
+++ b/MainModule/Server/Commands/Fun.luau
@@ -3756,18 +3756,20 @@ return function(Vargs, env)
end
local resizeAttributeValue = char:GetAttribute("Adonis_Resize")
- if not resizeAttributeValue then
- char:SetAttribute("Adonis_Resize", num)
- elseif resizeAttributeValue * num < Variables.SizeLimit then
- char:SetAttribute("Adonis_Resize", resizeAttributeValue * num)
- else
- Functions.Hint(string.format("Cannot resize %s's character by %g%%: size limit exceeded.", service.FormatPlayer(v), num*100), {plr})
- continue
+ local function setSizeAttribute(Val)
+ if not resizeAttributeValue or Val < Variables.SizeLimit then
+ char:SetAttribute("Adonis_Resize", Val)
+ else
+ error(string.format("Cannot resize %s's character by %g%%: size limit exceeded.", service.FormatPlayer(v), num*100))
+ end
end
if human and char:IsA("Model") then
+ setSizeAttribute(num)
char:ScaleTo(num)
elseif human and human.RigType == Enum.HumanoidRigType.R15 then
+ setSizeAttribute((resizeAttributeValue or 1) * num)
+
for _, val in human:GetChildren() do
if val:IsA("NumberValue") and val.Name:match(".*Scale") then
val.Value *= num
@@ -3775,6 +3777,8 @@ return function(Vargs, env)
end
fixDensity(char)
elseif human and human.RigType == Enum.HumanoidRigType.R6 then
+ setSizeAttribute((resizeAttributeValue or 1) * num)
+
local motors = {}
table.insert(motors, char.HumanoidRootPart:FindFirstChild("RootJoint"))
for _, motor in char.Torso:GetChildren() do
diff --git a/MainModule/Server/Commands/Moderators.luau b/MainModule/Server/Commands/Moderators.luau
index d3dbb77766..f240a7bd4c 100644
--- a/MainModule/Server/Commands/Moderators.luau
+++ b/MainModule/Server/Commands/Moderators.luau
@@ -6067,7 +6067,7 @@ return function(Vargs, env)
if oldga then oldga:Destroy() end
if olds then Remote.Send(v, "Function", "Unfly") olds:Destroy() end
- local new = scr:Clone()
+ local new = scr:Clone()
local flightPositionAttachment: Attachment = service.New("Attachment", {
Name = "ADONIS_FLIGHT_POSITION_ATTACHMENT",
Parent = part
@@ -6097,6 +6097,7 @@ return function(Vargs, env)
new.Disabled = false
end
end
+ scr:Destroy()
Functions.Hint("You are now flying - press E to toggle flight", service.GetPlayers(plr, args[1]), 10)
end
diff --git a/MainModule/Server/Core/Admin.luau b/MainModule/Server/Core/Admin.luau
index 441af6d8c4..b4f51f7615 100644
--- a/MainModule/Server/Core/Admin.luau
+++ b/MainModule/Server/Core/Admin.luau
@@ -1219,7 +1219,7 @@ return function(Vargs, GetEnv)
if Variables.ChatCreateRobloxCommands then
-- // Support for commands to be ran via TextChat
task.spawn(function()
- local container = service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService and service.TextChatService:WaitForChild("TextChatCommands", 9e9)
+ local container = service.TextChatService.ChatVersion == Enum.ChatVersion.TextChatService and service.TextChatService:WaitForChild("TextChatCommands", 120)
if container then
for _, v in container:GetChildren() do
diff --git a/MainModule/Server/Core/Remote.luau b/MainModule/Server/Core/Remote.luau
index 498fb89e48..64872cd2f0 100644
--- a/MainModule/Server/Core/Remote.luau
+++ b/MainModule/Server/Core/Remote.luau
@@ -134,6 +134,7 @@ return function(Vargs, GetEnv)
WhitelistedVariable = {
MusicList = true,
CodeName = true,
+ ChatCreateRobloxCommands = true,
};
Returnables = {
diff --git a/MainModule/Server/Dependencies/Assets/Clipper/init.client.luau b/MainModule/Server/Dependencies/Assets/Clipper/init.client.luau
index c9713a4b98..001d05ea13 100644
--- a/MainModule/Server/Dependencies/Assets/Clipper/init.client.luau
+++ b/MainModule/Server/Dependencies/Assets/Clipper/init.client.luau
@@ -2,11 +2,15 @@ local RunService = game:GetService("RunService")
local LIMB_NAMES = {
R6 = {
+ "CollisionPart",
+
"Torso",
"HumanoidRootPart",
"Head"
},
R15 = {
+ "CollisionPart",
+
"HumanoidRootPart",
"LowerTorso",
"UpperTorso"
diff --git a/MainModule/Server/Dependencies/Assets/Fly.client.luau b/MainModule/Server/Dependencies/Assets/Fly.client.luau
index 89481519b1..a87fc9bf12 100644
--- a/MainModule/Server/Dependencies/Assets/Fly.client.luau
+++ b/MainModule/Server/Dependencies/Assets/Fly.client.luau
@@ -128,6 +128,11 @@ function Stop()
flying = false
human.PlatformStand = false
+ local collisionPart: BasePart = human.Parent:FindFirstChild("CollisionPart")
+ if collisionPart then
+ collisionPart.CanCollide = true
+ end
+
if bPos then
bPos.MaxForce = 0
end
diff --git a/MainModule/Server/Dependencies/Assets/Freecam.rbxmx b/MainModule/Server/Dependencies/Assets/Freecam.rbxmx
deleted file mode 100644
index 3a4f85544a..0000000000
--- a/MainModule/Server/Dependencies/Assets/Freecam.rbxmx
+++ /dev/null
@@ -1,544 +0,0 @@
-
- true
- null
- nil
- -
-
-
- true
- 0
- true
- false
- Freecam
- false
-
[null]
- -1
-
- 1
-
- -
-
-
- true
-
- Freecam
- {767B5CA6-BE25-4C4F-943A-28FA91C505BF}
- dist then
- minDist = dist
- minVect = offset.unit
- end
- end
- end
-
- return fz:Dot(minVect)*minDist
-end
-
-------------------------------------------------------------------------
-
-local function StepFreecam(dt)
- local vel = velSpring:Update(dt, Input.Vel(dt))
- local pan = panSpring:Update(dt, Input.Pan(dt))
- local fov = fovSpring:Update(dt, Input.Fov(dt))
-
- local zoomFactor = sqrt(tan(rad(70/2))/tan(rad(cameraFov/2)))
-
- cameraFov = clamp(cameraFov + fov*FOV_GAIN*(dt/zoomFactor), 1, 120)
- cameraRot = cameraRot + pan*PAN_GAIN*(dt/zoomFactor)
- cameraRot = Vector2.new(clamp(cameraRot.x, -PITCH_LIMIT, PITCH_LIMIT), cameraRot.y%(2*pi))
-
- local cameraCFrame = CFrame.new(cameraPos)*CFrame.fromOrientation(cameraRot.x, cameraRot.y, 0)*CFrame.new(vel*NAV_GAIN*dt)
- cameraPos = cameraCFrame.p
-
- Camera.CFrame = cameraCFrame
- Camera.Focus = cameraCFrame*CFrame.new(0, 0, -GetFocusDistance(cameraCFrame))
- Camera.FieldOfView = cameraFov
-end
-
-------------------------------------------------------------------------
-
-local PlayerState = {} do
- local mouseBehavior
- local mouseIconEnabled
- local cameraType
- local cameraFocus
- local cameraCFrame
- local cameraFieldOfView
- local screenGuis = {}
- local coreGuis = {
- Backpack = true,
- Chat = true,
- Health = true,
- PlayerList = true,
- }
- local setCores = {
- BadgesNotificationsActive = true,
- PointsNotificationsActive = true,
- }
-
- -- Save state and set up for freecam
- function PlayerState.Push()
- for name in pairs(coreGuis) do
- coreGuis[name] = StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType[name])
- StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], false)
- end
- for name in pairs(setCores) do
- setCores[name] = StarterGui:GetCore(name)
- StarterGui:SetCore(name, false)
- end
- local playergui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
- if playergui then
- for _, gui in pairs(playergui:GetChildren()) do
- if gui:IsA("ScreenGui") and gui.Enabled then
- screenGuis[#screenGuis + 1] = gui
- gui.Enabled = false
- end
- end
- end
-
- cameraFieldOfView = Camera.FieldOfView
- Camera.FieldOfView = 70
-
- cameraType = Camera.CameraType
- Camera.CameraType = Enum.CameraType.Custom
-
- cameraCFrame = Camera.CFrame
- cameraFocus = Camera.Focus
-
- mouseIconEnabled = UserInputService.MouseIconEnabled
- UserInputService.MouseIconEnabled = false
-
- mouseBehavior = UserInputService.MouseBehavior
- UserInputService.MouseBehavior = Enum.MouseBehavior.Default
- end
-
- -- Restore state
- function PlayerState.Pop()
- if cameraFieldOfView == nil then return end
- for name, isEnabled in pairs(coreGuis) do
- StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], isEnabled)
- end
- for name, isEnabled in pairs(setCores) do
- StarterGui:SetCore(name, isEnabled)
- end
- for _, gui in pairs(screenGuis) do
- if gui.Parent then
- gui.Enabled = true
- end
- end
-
- Camera.FieldOfView = cameraFieldOfView
- cameraFieldOfView = nil
-
- Camera.CameraType = cameraType
- cameraType = nil
-
- Camera.CFrame = cameraCFrame
- cameraCFrame = nil
-
- Camera.Focus = cameraFocus
- cameraFocus = nil
-
- UserInputService.MouseIconEnabled = mouseIconEnabled
- mouseIconEnabled = nil
-
- UserInputService.MouseBehavior = mouseBehavior
- mouseBehavior = nil
- end
-end
-
-local function StartFreecam()
- local cameraCFrame = Camera.CFrame
- cameraRot = Vector2.new(cameraCFrame:toEulerAnglesYXZ())
- cameraPos = cameraCFrame.p
- cameraFov = Camera.FieldOfView
-
- velSpring:Reset(Vector3.new())
- panSpring:Reset(Vector2.new())
- fovSpring:Reset(0)
-
- PlayerState.Push()
- RunService:BindToRenderStep("Freecam", Enum.RenderPriority.Camera.Value, StepFreecam)
- Input.StartCapture()
- UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
-end
-
-local function StopFreecam()
- Input.StopCapture()
- RunService:UnbindFromRenderStep("Freecam")
- PlayerState.Pop()
- UserInputService.MouseBehavior = Enum.MouseBehavior.Default
-end
-
-------------------------------------------------------------------------
-
-do
- local enabled = false
-
- local function ToggleFreecam()
- if enabled then
- StopFreecam()
- else
- StartFreecam()
- end
- enabled = not enabled
- end
-
- local function CheckMacro(macro)
- for i = 1, #macro - 1 do
- if not UserInputService:IsKeyDown(macro[i]) then
- return
- end
- end
- ToggleFreecam()
- end
-
- local function HandleActivationInput(action, state, input)
- if state == Enum.UserInputState.Begin then
- if input.KeyCode == FREECAM_MACRO_KB[#FREECAM_MACRO_KB] then
- CheckMacro(FREECAM_MACRO_KB)
- end
-
- if input.KeyCode == Enum.KeyCode.F or input.KeyCode == Enum.KeyCode.DPadLeft then
- ToggleFreecam()
- end
- end
- return Enum.ContextActionResult.Pass
- end
-
- ContextActionService:BindActionAtPriority("FreecamToggle", HandleActivationInput, false, TOGGLE_INPUT_PRIORITY, FREECAM_MACRO_KB[#FREECAM_MACRO_KB])
- ContextActionService:BindActionAtPriority("FreecamToggle2", HandleActivationInput, false, TOGGLE_INPUT_PRIORITY, Enum.KeyCode.F)
- ContextActionService:BindActionAtPriority("FreecamToggleDPAD", HandleActivationInput, false, TOGGLE_INPUT_PRIORITY, Enum.KeyCode.DPadLeft)
-
- RF.OnClientInvoke = function(a, b, c)
- if a == "Disable" and enabled then
- enabled = false
- StopFreecam()
- end
-
- if a == "Enable" and not enabled then
- enabled = true
- StartFreecam()
- end
-
- if a == "Toggle" then
- ToggleFreecam()
- end
-
- if a == "End" or a == "Stop" then
- RF.OnClientInvoke = nil
- Debris:AddItem(RF, 0.5)
- ContextActionService:UnbindAction("FreecamToggle")
- ContextActionService:UnbindAction("FreecamToggle2")
- ContextActionService:UnbindAction("FreecamToggleDPAD")
- StopFreecam()
- end
- end
-end]]>
- -1
-
-
-
- -
-
-
- Remote
- -1
-
-
-
-
-
diff --git a/MainModule/Server/Dependencies/Assets/Freecam/Freecam.client.lua b/MainModule/Server/Dependencies/Assets/Freecam/Freecam.client.lua
new file mode 100644
index 0000000000..bd8940dfa5
--- /dev/null
+++ b/MainModule/Server/Dependencies/Assets/Freecam/Freecam.client.lua
@@ -0,0 +1,1173 @@
+--!nonstrict
+------------------------------------------------------------------------
+-- Freecam
+-- Cinematic free camera for spectating and video production.
+------------------------------------------------------------------------
+
+local pi = math.pi
+local abs = math.abs
+local clamp = math.clamp
+local exp = math.exp
+local rad = math.rad
+local sign = math.sign
+local sqrt = math.sqrt
+local tan = math.tan
+
+local ContextActionService = game:GetService("ContextActionService")
+local Players = game:GetService("Players")
+local RunService = game:GetService("RunService")
+local StarterGui = game:GetService("StarterGui")
+local UserInputService = game:GetService("UserInputService")
+local Workspace = game:GetService("Workspace")
+local Settings = UserSettings()
+local GameSettings = Settings.GameSettings
+local Lighting = game:GetService("Lighting")
+local Debris = game:GetService('Debris')
+local RF = script.Parent:FindFirstChildOfClass("RemoteFunction")
+
+local LocalPlayer = Players.LocalPlayer
+if not LocalPlayer then
+ Players:GetPropertyChangedSignal("LocalPlayer"):Wait()
+ LocalPlayer = Players.LocalPlayer
+end
+
+local Camera = Workspace.CurrentCamera
+Workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
+ local newCamera = Workspace.CurrentCamera
+ if newCamera then
+ Camera = newCamera
+ end
+end)
+
+local FreecamDepthOfField = nil
+
+local FFlagUserExitFreecamBreaksWithShiftlock
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserExitFreecamBreaksWithShiftlock")
+ end)
+ FFlagUserExitFreecamBreaksWithShiftlock = success and result
+end
+
+local FFlagUserShowGuiHideToggles
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserShowGuiHideToggles")
+ end)
+ FFlagUserShowGuiHideToggles = success and result
+end
+
+local FFlagUserFixFreecamDeltaTimeCalculation
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserFixFreecamDeltaTimeCalculation")
+ end)
+ FFlagUserFixFreecamDeltaTimeCalculation = success and result
+end
+
+local FFlagUserFixFreecamGuiChangeVisibility
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserFixFreecamGuiChangeVisibility")
+ end)
+ FFlagUserFixFreecamGuiChangeVisibility = success and result
+end
+
+local FFlagUserFreecamControlSpeed
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserFreecamControlSpeed")
+ end)
+ FFlagUserFreecamControlSpeed = success and result
+end
+
+local FFlagUserFreecamTiltControl
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserFreecamTiltControl")
+ end)
+ FFlagUserFreecamTiltControl = success and result
+end
+
+local FFlagUserFreecamSmoothnessControl
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserFreecamSmoothnessControl")
+ end)
+ FFlagUserFreecamSmoothnessControl = success and result
+end
+
+local FFlagUserFreecamGuiDestabilization
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserFreecamGuiDestabilization")
+ end)
+ FFlagUserFreecamGuiDestabilization = success and result
+end
+
+local FFlagUserFreecamDepthOfFieldEffect
+do
+ local success, result = pcall(function()
+ return UserSettings():IsUserFeatureEnabled("UserFreecamDepthOfFieldEffect")
+ end)
+ FFlagUserFreecamDepthOfFieldEffect = success and result
+end
+
+------------------------------------------------------------------------
+
+local FREECAM_ENABLED_ATTRIBUTE_NAME = "FreecamEnabled"
+local TOGGLE_INPUT_PRIORITY = Enum.ContextActionPriority.Low.Value
+local INPUT_PRIORITY = Enum.ContextActionPriority.High.Value
+local FREECAM_MACRO_KB = { Enum.KeyCode.LeftShift, Enum.KeyCode.P }
+local FREECAM_TILT_RESET_KB = {
+ [Enum.KeyCode.Z] = true,
+ [Enum.KeyCode.C] = true,
+}
+local FREECAM_TILT_RESET_GP = {
+ [Enum.KeyCode.ButtonL1] = true,
+ [Enum.KeyCode.ButtonR1] = true,
+}
+local FREECAM_DOF_TOGGLE = {
+ [Enum.KeyCode.BackSlash] = true,
+}
+
+local NAV_GAIN = Vector3.new(1, 1, 1) * 64
+local PAN_GAIN = Vector2.new(0.75, 1) * 8
+local FOV_GAIN = 300
+local ROLL_GAIN = -pi / 2
+
+local PITCH_LIMIT = rad(90)
+
+local VEL_STIFFNESS = 1.5
+local PAN_STIFFNESS = 1.0
+local FOV_STIFFNESS = 4.0
+local ROLL_STIFFNESS = 1.0
+
+local VEL_ADJ_STIFFNESS = 0.75
+local PAN_ADJ_STIFFNESS = 0.75
+local FOV_ADJ_STIFFNESS = 0.75
+local ROLL_ADJ_STIFFNESS = 0.75
+
+local VEL_MIN_STIFFNESS = 0.01
+local PAN_MIN_STIFFNESS = 0.01
+local FOV_MIN_STIFFNESS = 0.01
+local ROLL_MIN_STIFFNESS = 0.01
+
+local VEL_MAX_STIFFNESS = 10.0
+local PAN_MAX_STIFFNESS = 10.0
+local FOV_MAX_STIFFNESS = 10.0
+local ROLL_MAX_STIFFNESS = 10.0
+
+local lastPressTime = {}
+local lastResetTime = 0
+local DOUBLE_TAP_TIME_THRESHOLD = 0.25
+local DOUBLE_TAP_DEBOUNCE_TIME = 0.1
+
+local postEffects = {}
+------------------------------------------------------------------------
+
+local Spring = {}
+do
+ Spring.__index = Spring
+
+ function Spring.new(freq, pos)
+ local self = setmetatable({}, Spring)
+ self.f = freq
+ self.p = pos
+ self.v = pos * 0
+ return self
+ end
+
+ function Spring:Update(dt, goal)
+ local f = self.f * 2 * pi
+ local p0 = self.p
+ local v0 = self.v
+
+ local offset = goal - p0
+ local decay = exp(-f * dt)
+
+ local p1 = goal + (v0 * dt - offset * (f * dt + 1)) * decay
+ local v1 = (f * dt * (offset * f - v0) + v0) * decay
+
+ self.p = p1
+ self.v = v1
+
+ return p1
+ end
+
+ function Spring:SetFreq(freq)
+ self.f = freq
+ end
+
+ function Spring:Reset(pos)
+ self.p = pos
+ self.v = pos * 0
+ end
+end
+
+------------------------------------------------------------------------
+
+local cameraPos = Vector3.new()
+local cameraRot
+if FFlagUserFreecamTiltControl then
+ cameraRot = Vector3.new()
+else
+ cameraRot = Vector2.new()
+end
+local cameraFov = 0
+
+local velSpring = Spring.new(VEL_STIFFNESS, Vector3.new())
+local panSpring = Spring.new(PAN_STIFFNESS, Vector2.new())
+local fovSpring = Spring.new(FOV_STIFFNESS, 0)
+local rollSpring = Spring.new(ROLL_STIFFNESS, 0)
+
+------------------------------------------------------------------------
+
+local Input = {}
+do
+ local thumbstickCurve
+ do
+ local K_CURVATURE = 2.0
+ local K_DEADZONE = 0.15
+
+ local function fCurve(x)
+ return (exp(K_CURVATURE * x) - 1) / (exp(K_CURVATURE) - 1)
+ end
+
+ local function fDeadzone(x)
+ return fCurve((x - K_DEADZONE) / (1 - K_DEADZONE))
+ end
+
+ function thumbstickCurve(x)
+ return sign(x) * clamp(fDeadzone(abs(x)), 0, 1)
+ end
+ end
+
+ local gamepad = {
+ ButtonX = 0,
+ ButtonY = 0,
+ DPadDown = 0,
+ DPadUp = 0,
+ DPadLeft = 0,
+ DPadRight = 0,
+ ButtonL2 = 0,
+ ButtonR2 = 0,
+ ButtonL1 = 0,
+ ButtonR1 = 0,
+ Thumbstick1 = Vector2.new(),
+ Thumbstick2 = Vector2.new(),
+ }
+
+ local keyboard = {
+ W = 0,
+ A = 0,
+ S = 0,
+ D = 0,
+ E = 0,
+ Q = 0,
+ U = 0,
+ H = 0,
+ J = 0,
+ K = 0,
+ I = 0,
+ Y = 0,
+ Up = 0,
+ Down = 0,
+ Left = 0,
+ Right = 0,
+ LeftShift = 0,
+ RightShift = 0,
+ Z = 0,
+ C = 0,
+ Comma = 0,
+ Period = 0,
+ LeftBracket = 0,
+ RightBracket = 0,
+ Semicolon = 0,
+ Quote = 0,
+ V = 0,
+ B = 0,
+ N = 0,
+ M = 0,
+ BackSlash = 0,
+ Minus = 0,
+ Equals = 0,
+ }
+
+ local mouse = {
+ Delta = Vector2.new(),
+ MouseWheel = 0,
+ }
+
+ local DEFAULT_FPS = 60
+ local NAV_GAMEPAD_SPEED = Vector3.new(1, 1, 1)
+ local NAV_KEYBOARD_SPEED = Vector3.new(1, 1, 1)
+ local PAN_MOUSE_SPEED = Vector2.new(1, 1) * (pi / 64)
+ local PAN_MOUSE_SPEED_DT = PAN_MOUSE_SPEED / DEFAULT_FPS
+ local PAN_GAMEPAD_SPEED = Vector2.new(1, 1) * (pi / 8)
+ local FOV_WHEEL_SPEED = 1.0
+ local FOV_WHEEL_SPEED_DT = FOV_WHEEL_SPEED / DEFAULT_FPS
+ local FOV_GAMEPAD_SPEED = 0.25
+ local ROLL_GAMEPAD_SPEED = 1.0
+ local ROLL_KEYBOARD_SPEED = 1.0
+ local NAV_ADJ_SPEED = 0.75
+ local NAV_MIN_SPEED = 0.01
+ local NAV_MAX_SPEED = 4.0
+ local NAV_SHIFT_MUL = 0.25
+ local FOV_ADJ_SPEED = 0.75
+ local FOV_MIN_SPEED = 0.01
+ local FOV_MAX_SPEED = 4.0
+ local ROLL_ADJ_SPEED = 0.75
+ local ROLL_MIN_SPEED = 0.01
+ local ROLL_MAX_SPEED = 4.0
+ local DoFConstants = {
+ FarIntensity = {
+ ADJ = 0.1,
+ MIN = 0.0,
+ MAX = 1.0,
+ },
+ NearIntensity = {
+ ADJ = 0.1,
+ MIN = 0.0,
+ MAX = 1.0,
+ },
+ FocusDistance = {
+ ADJ = 20.0,
+ MIN = 0.0,
+ MAX = 200.0,
+ },
+ FocusRadius = {
+ ADJ = 5.0,
+ MIN = 0.0,
+ MAX = 50.0,
+ },
+ }
+
+ local navSpeed = 1
+ local rollSpeed = 1
+ local fovSpeed = 1
+
+ function Input.Vel(dt)
+ if FFlagUserFreecamControlSpeed then
+ navSpeed = clamp(
+ navSpeed + dt * (keyboard.Up - keyboard.Down + gamepad.DPadUp - gamepad.DPadDown) * NAV_ADJ_SPEED,
+ NAV_MIN_SPEED,
+ NAV_MAX_SPEED
+ )
+ else
+ navSpeed = clamp(navSpeed + dt * (keyboard.Up - keyboard.Down) * NAV_ADJ_SPEED, 0.01, 4)
+ end
+ local kGamepad = Vector3.new(
+ thumbstickCurve(gamepad.Thumbstick1.X),
+ thumbstickCurve(gamepad.ButtonR2) - thumbstickCurve(gamepad.ButtonL2),
+ thumbstickCurve(-gamepad.Thumbstick1.Y)
+ ) * NAV_GAMEPAD_SPEED
+
+ local kKeyboard = Vector3.new(
+ keyboard.D - keyboard.A + keyboard.K - keyboard.H,
+ keyboard.E - keyboard.Q + keyboard.I - keyboard.Y,
+ keyboard.S - keyboard.W + keyboard.J - keyboard.U
+ ) * NAV_KEYBOARD_SPEED
+
+ local shift = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift)
+ or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)
+
+ return (kGamepad + kKeyboard) * (navSpeed * (shift and NAV_SHIFT_MUL or 1))
+ end
+
+ function Input.Pan(dt)
+ local kGamepad = Vector2.new(thumbstickCurve(gamepad.Thumbstick2.Y), thumbstickCurve(-gamepad.Thumbstick2.X))
+ * PAN_GAMEPAD_SPEED
+ local kMouse = mouse.Delta * PAN_MOUSE_SPEED
+ if FFlagUserFixFreecamDeltaTimeCalculation then
+ if dt > 0 then
+ kMouse = (mouse.Delta / dt) * PAN_MOUSE_SPEED_DT
+ end
+ end
+ mouse.Delta = Vector2.new()
+ return kGamepad + kMouse
+ end
+
+ function Input.Fov(dt)
+ if FFlagUserFreecamControlSpeed then
+ fovSpeed = clamp(
+ fovSpeed + dt * (keyboard.Right - keyboard.Left + gamepad.DPadRight - gamepad.DPadLeft) * FOV_ADJ_SPEED,
+ FOV_MIN_SPEED,
+ FOV_MAX_SPEED
+ )
+ end
+ local kGamepad = (gamepad.ButtonX - gamepad.ButtonY) * FOV_GAMEPAD_SPEED
+ local kMouse = mouse.MouseWheel * FOV_WHEEL_SPEED
+ if FFlagUserFixFreecamDeltaTimeCalculation then
+ if dt > 0 then
+ kMouse = (mouse.MouseWheel / dt) * FOV_WHEEL_SPEED_DT
+ end
+ end
+ mouse.MouseWheel = 0
+ if FFlagUserFreecamControlSpeed then
+ return (kGamepad + kMouse) * fovSpeed
+ else
+ return kGamepad + kMouse
+ end
+ end
+
+ function Input.Roll(dt)
+ rollSpeed =
+ clamp(rollSpeed + dt * (keyboard.Period - keyboard.Comma) * ROLL_ADJ_SPEED, ROLL_MIN_SPEED, ROLL_MAX_SPEED)
+
+ local kGamepad = (gamepad.ButtonR1 - gamepad.ButtonL1) * ROLL_GAMEPAD_SPEED
+ local kKeyboard = (keyboard.C - keyboard.Z) * ROLL_KEYBOARD_SPEED
+
+ return (kGamepad + kKeyboard) * rollSpeed
+ end
+
+ function Input.SpringControl(dt)
+ if FFlagUserFreecamDepthOfFieldEffect then
+ local shiftIsDown = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift)
+ or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)
+ local ctrlIsDown = UserInputService:IsKeyDown(Enum.KeyCode.LeftControl)
+ or UserInputService:IsKeyDown(Enum.KeyCode.RightControl)
+
+ if shiftIsDown or ctrlIsDown then
+ return -- reserve Shift+Keybinds for other actions, in this case Shift+Brackets for Depth of Field controls
+ end
+ end
+
+ VEL_STIFFNESS = clamp(
+ VEL_STIFFNESS + dt * (keyboard.RightBracket - keyboard.LeftBracket) * VEL_ADJ_STIFFNESS,
+ VEL_MIN_STIFFNESS,
+ VEL_MAX_STIFFNESS
+ )
+ velSpring:SetFreq(VEL_STIFFNESS)
+
+ PAN_STIFFNESS = clamp(
+ PAN_STIFFNESS + dt * (keyboard.Quote - keyboard.Semicolon) * PAN_ADJ_STIFFNESS,
+ PAN_MIN_STIFFNESS,
+ PAN_MAX_STIFFNESS
+ )
+ panSpring:SetFreq(PAN_STIFFNESS)
+
+ FOV_STIFFNESS = clamp(
+ FOV_STIFFNESS + dt * (keyboard.B - keyboard.V) * FOV_ADJ_STIFFNESS,
+ FOV_MIN_STIFFNESS,
+ FOV_MAX_STIFFNESS
+ )
+ fovSpring:SetFreq(FOV_STIFFNESS)
+
+ ROLL_STIFFNESS = clamp(
+ ROLL_STIFFNESS + dt * (keyboard.M - keyboard.N) * ROLL_ADJ_STIFFNESS,
+ ROLL_MIN_STIFFNESS,
+ ROLL_MAX_STIFFNESS
+ )
+ rollSpring:SetFreq(ROLL_STIFFNESS)
+ end
+
+ function Input.DoF(dt)
+ local shiftIsDown = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift)
+ or UserInputService:IsKeyDown(Enum.KeyCode.RightShift)
+ local ctrlIsDown = UserInputService:IsKeyDown(Enum.KeyCode.LeftControl)
+ or UserInputService:IsKeyDown(Enum.KeyCode.RightControl)
+
+ if shiftIsDown then
+ FreecamDepthOfField.FarIntensity = clamp(
+ FreecamDepthOfField.FarIntensity
+ + dt * (keyboard.RightBracket - keyboard.LeftBracket) * DoFConstants.FarIntensity.ADJ,
+ DoFConstants.FarIntensity.MIN,
+ DoFConstants.FarIntensity.MAX
+ )
+ FreecamDepthOfField.InFocusRadius = clamp(
+ FreecamDepthOfField.InFocusRadius
+ + dt * (keyboard.Equals - keyboard.Minus) * DoFConstants.FocusRadius.ADJ,
+ DoFConstants.FocusRadius.MIN,
+ DoFConstants.FocusRadius.MAX
+ )
+ elseif ctrlIsDown then
+ FreecamDepthOfField.NearIntensity = clamp(
+ FreecamDepthOfField.NearIntensity
+ + dt * (keyboard.RightBracket - keyboard.LeftBracket) * DoFConstants.NearIntensity.ADJ,
+ DoFConstants.NearIntensity.MIN,
+ DoFConstants.NearIntensity.MAX
+ )
+ else
+ FreecamDepthOfField.FocusDistance = clamp(
+ FreecamDepthOfField.FocusDistance
+ + dt * (keyboard.Equals - keyboard.Minus) * DoFConstants.FocusDistance.ADJ,
+ DoFConstants.FocusDistance.MIN,
+ DoFConstants.FocusDistance.MAX
+ )
+ end
+ end
+
+ do
+ local function resetKeys(keys, table)
+ for keyEnum, _ in pairs(keys) do
+ if table[keyEnum.Name] then
+ table[keyEnum.Name] = 0
+ end
+ end
+ end
+
+ local function handleDoubleTapReset(keyCode)
+ local currentTime = os.clock()
+
+ local previousPressTime = lastPressTime[keyCode]
+ local timeSinceLastPress = previousPressTime and (currentTime - previousPressTime) or -1
+
+ if previousPressTime and (timeSinceLastPress <= DOUBLE_TAP_TIME_THRESHOLD) then
+ if (currentTime - lastResetTime) >= DOUBLE_TAP_DEBOUNCE_TIME then
+ cameraRot = Vector3.new(cameraRot.x, cameraRot.y, 0)
+ rollSpring:Reset(0)
+ if FFlagUserFreecamDepthOfFieldEffect then
+ resetKeys(FREECAM_TILT_RESET_GP, gamepad)
+ resetKeys(FREECAM_TILT_RESET_KB, keyboard)
+ else
+ gamepad.ButtonL1 = 0
+ gamepad.ButtonR1 = 0
+ keyboard.C = 0
+ keyboard.Z = 0
+ end
+ lastResetTime = currentTime
+ end
+ end
+ lastPressTime[keyCode] = currentTime
+ end
+
+ local function Keypress(action, state, input)
+ keyboard[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
+
+ if FFlagUserFreecamTiltControl then
+ if FREECAM_TILT_RESET_KB[input.KeyCode] and input.UserInputState == Enum.UserInputState.Begin then
+ handleDoubleTapReset(input.KeyCode)
+ end
+ end
+
+ if FFlagUserFreecamDepthOfFieldEffect then
+ if FREECAM_DOF_TOGGLE[input.KeyCode] and input.UserInputState == Enum.UserInputState.Begin then
+ if not FreecamDepthOfField.Enabled then
+ postEffects = {}
+ -- Disable all existing DepthOfFieldEffects to be controlled by custom Freecam DoF.
+ for _, effect in ipairs(Camera:GetChildren()) do
+ if effect:IsA("DepthOfFieldEffect") and effect.Enabled then
+ postEffects[#postEffects + 1] = effect
+ effect.Enabled = false
+ end
+ end
+ for _, effect in ipairs(Lighting:GetChildren()) do
+ if effect:IsA("DepthOfFieldEffect") and effect.Enabled then
+ postEffects[#postEffects + 1] = effect
+ effect.Enabled = false
+ end
+ end
+ Camera.ChildAdded:Connect(function(child)
+ if child:IsA("DepthOfFieldEffect") and child.Enabled then
+ postEffects[#postEffects + 1] = child
+ child.Enabled = false
+ end
+ end)
+ Lighting.ChildAdded:Connect(function(child)
+ if child:IsA("DepthOfFieldEffect") and child.Enabled then
+ postEffects[#postEffects + 1] = child
+ child.Enabled = false
+ end
+ end)
+ else
+ -- Re-enable all existing DepthOfFieldEffects when custom Freecam DoF is off.
+ for _, effect in ipairs(postEffects) do
+ if effect.Parent then
+ effect.Enabled = true
+ end
+ end
+ postEffects = {}
+ end
+ FreecamDepthOfField.Enabled = not FreecamDepthOfField.Enabled
+ resetKeys(FREECAM_DOF_TOGGLE, keyboard)
+ end
+ end
+
+ return Enum.ContextActionResult.Sink
+ end
+
+ local function GpButton(action, state, input)
+ gamepad[input.KeyCode.Name] = state == Enum.UserInputState.Begin and 1 or 0
+
+ if FFlagUserFreecamTiltControl then
+ if FREECAM_TILT_RESET_GP[input.KeyCode] and input.UserInputState == Enum.UserInputState.Begin then
+ handleDoubleTapReset(input.KeyCode)
+ end
+ end
+
+ return Enum.ContextActionResult.Sink
+ end
+
+ local function MousePan(action, state, input)
+ local delta = input.Delta
+ mouse.Delta = Vector2.new(-delta.y, -delta.x)
+ return Enum.ContextActionResult.Sink
+ end
+
+ local function Thumb(action, state, input)
+ gamepad[input.KeyCode.Name] = input.Position
+ return Enum.ContextActionResult.Sink
+ end
+
+ local function Trigger(action, state, input)
+ gamepad[input.KeyCode.Name] = input.Position.z
+ return Enum.ContextActionResult.Sink
+ end
+
+ local function MouseWheel(action, state, input)
+ mouse[input.UserInputType.Name] = -input.Position.z
+ return Enum.ContextActionResult.Sink
+ end
+
+ local function Zero(t)
+ for k, v in pairs(t) do
+ t[k] = v * 0
+ end
+ end
+
+ function Input.StartCapture()
+ if FFlagUserFreecamControlSpeed then
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboard",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.W,
+ Enum.KeyCode.U,
+ Enum.KeyCode.A,
+ Enum.KeyCode.H,
+ Enum.KeyCode.S,
+ Enum.KeyCode.J,
+ Enum.KeyCode.D,
+ Enum.KeyCode.K,
+ Enum.KeyCode.E,
+ Enum.KeyCode.I,
+ Enum.KeyCode.Q,
+ Enum.KeyCode.Y
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboardControlSpeed",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.Up,
+ Enum.KeyCode.Down,
+ Enum.KeyCode.Left,
+ Enum.KeyCode.Right
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamGamepadControlSpeed",
+ GpButton,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.DPadUp,
+ Enum.KeyCode.DPadDown,
+ --Enum.KeyCode.DPadLeft, -- So this was bit of a problem because we use DPadLeft to toggle it but Roblox had some other ideas
+ Enum.KeyCode.DPadRight -- I myself would move the freecam toggle to another key but i dont know if that is a good idea. Well it will be someone else's problem now.
+ )
+ else
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboard",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.W,
+ Enum.KeyCode.U,
+ Enum.KeyCode.A,
+ Enum.KeyCode.H,
+ Enum.KeyCode.S,
+ Enum.KeyCode.J,
+ Enum.KeyCode.D,
+ Enum.KeyCode.K,
+ Enum.KeyCode.E,
+ Enum.KeyCode.I,
+ Enum.KeyCode.Q,
+ Enum.KeyCode.Y,
+ Enum.KeyCode.Up,
+ Enum.KeyCode.Down
+ )
+ end
+ if FFlagUserFreecamTiltControl then
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboardTiltControl",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.Z,
+ Enum.KeyCode.C
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamGamepadTiltControl",
+ GpButton,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.ButtonL1,
+ Enum.KeyCode.ButtonR1
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboardTiltControlSpeed",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.Comma,
+ Enum.KeyCode.Period
+ )
+ if FFlagUserFreecamSmoothnessControl then
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboardSmoothnessControl",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.LeftBracket,
+ Enum.KeyCode.RightBracket,
+ Enum.KeyCode.Semicolon,
+ Enum.KeyCode.Quote,
+ Enum.KeyCode.V,
+ Enum.KeyCode.B,
+ Enum.KeyCode.N,
+ Enum.KeyCode.M
+ )
+ end
+ end
+ if FFlagUserFreecamDepthOfFieldEffect then
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboardDoFToggle",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.BackSlash
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamKeyboardDoFControls",
+ Keypress,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.Minus,
+ Enum.KeyCode.Equals
+ )
+ end
+ ContextActionService:BindActionAtPriority(
+ "FreecamMousePan",
+ MousePan,
+ false,
+ INPUT_PRIORITY,
+ Enum.UserInputType.MouseMovement
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamMouseWheel",
+ MouseWheel,
+ false,
+ INPUT_PRIORITY,
+ Enum.UserInputType.MouseWheel
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamGamepadButton",
+ GpButton,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.ButtonX,
+ Enum.KeyCode.ButtonY
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamGamepadTrigger",
+ Trigger,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.ButtonR2,
+ Enum.KeyCode.ButtonL2
+ )
+ ContextActionService:BindActionAtPriority(
+ "FreecamGamepadThumbstick",
+ Thumb,
+ false,
+ INPUT_PRIORITY,
+ Enum.KeyCode.Thumbstick1,
+ Enum.KeyCode.Thumbstick2
+ )
+ end
+
+ function Input.StopCapture()
+ navSpeed = 1
+ if FFlagUserFreecamControlSpeed then
+ fovSpeed = 1
+ end
+ if FFlagUserFreecamTiltControl then
+ rollSpeed = 1
+ end
+ Zero(gamepad)
+ Zero(keyboard)
+ Zero(mouse)
+ ContextActionService:UnbindAction("FreecamKeyboard")
+ if FFlagUserFreecamControlSpeed then
+ ContextActionService:UnbindAction("FreecamKeyboardControlSpeed")
+ ContextActionService:UnbindAction("FreecamGamepadControlSpeed")
+ end
+ if FFlagUserFreecamTiltControl then
+ ContextActionService:UnbindAction("FreecamKeyboardTiltControl")
+ ContextActionService:UnbindAction("FreecamGamepadTiltControl")
+ ContextActionService:UnbindAction("FreecamKeyboardTiltControlSpeed")
+ if FFlagUserFreecamSmoothnessControl then
+ ContextActionService:UnbindAction("FreecamKeyboardSmoothnessControl")
+ end
+ end
+ if FFlagUserFreecamDepthOfFieldEffect then
+ ContextActionService:UnbindAction("FreecamKeyboardDoFToggle")
+ ContextActionService:UnbindAction("FreecamKeyboardDoFControls")
+ end
+ ContextActionService:UnbindAction("FreecamMousePan")
+ ContextActionService:UnbindAction("FreecamMouseWheel")
+ ContextActionService:UnbindAction("FreecamGamepadButton")
+ ContextActionService:UnbindAction("FreecamGamepadTrigger")
+ ContextActionService:UnbindAction("FreecamGamepadThumbstick")
+ end
+ end
+end
+
+------------------------------------------------------------------------
+
+local function StepFreecam(dt)
+ if FFlagUserFreecamSmoothnessControl then
+ Input.SpringControl(dt)
+ end
+
+ if FFlagUserFreecamDepthOfFieldEffect then
+ if FreecamDepthOfField and FreecamDepthOfField.Parent then
+ Input.DoF(dt)
+ end
+ end
+
+ local vel = velSpring:Update(dt, Input.Vel(dt))
+ local pan = panSpring:Update(dt, Input.Pan(dt))
+ local fov = fovSpring:Update(dt, Input.Fov(dt))
+ local roll
+ if FFlagUserFreecamTiltControl then
+ roll = rollSpring:Update(dt, Input.Roll(dt))
+ end
+
+ local zoomFactor = sqrt(tan(rad(70 / 2)) / tan(rad(cameraFov / 2)))
+
+ cameraFov = clamp(cameraFov + fov * FOV_GAIN * (dt / zoomFactor), 1, 120)
+ local cameraCFrame
+ if FFlagUserFreecamTiltControl then
+ local panVector: Vector2 = pan * PAN_GAIN * (dt / zoomFactor)
+ cameraRot = cameraRot + Vector3.new(panVector.X, panVector.Y, roll * ROLL_GAIN * (dt / zoomFactor))
+ if FFlagUserFreecamSmoothnessControl then
+ cameraRot = Vector3.new(cameraRot.x % (2 * pi), cameraRot.y % (2 * pi), cameraRot.z % (2 * pi))
+ else
+ cameraRot = Vector3.new(clamp(cameraRot.x, -PITCH_LIMIT, PITCH_LIMIT), cameraRot.y % (2 * pi), cameraRot.z)
+ end
+
+ cameraCFrame = CFrame.new(cameraPos)
+ * CFrame.fromOrientation(cameraRot.x, cameraRot.y, cameraRot.z)
+ * CFrame.new(vel * NAV_GAIN * dt)
+ else
+ cameraRot = cameraRot + pan * PAN_GAIN * (dt / zoomFactor)
+ cameraRot = Vector2.new(clamp(cameraRot.x, -PITCH_LIMIT, PITCH_LIMIT), cameraRot.y % (2 * pi))
+
+ cameraCFrame = CFrame.new(cameraPos)
+ * CFrame.fromOrientation(cameraRot.x, cameraRot.y, 0)
+ * CFrame.new(vel * NAV_GAIN * dt)
+ end
+
+ cameraPos = cameraCFrame.p
+
+ Camera.CFrame = cameraCFrame
+ Camera.Focus = cameraCFrame
+ Camera.FieldOfView = cameraFov
+end
+
+local function CheckMouseLockAvailability()
+ local devAllowsMouseLock = Players.LocalPlayer.DevEnableMouseLock
+ local devMovementModeIsScriptable = Players.LocalPlayer.DevComputerMovementMode
+ == Enum.DevComputerMovementMode.Scriptable
+ local userHasMouseLockModeEnabled = GameSettings.ControlMode == Enum.ControlMode.MouseLockSwitch
+ local userHasClickToMoveEnabled = GameSettings.ComputerMovementMode == Enum.ComputerMovementMode.ClickToMove
+ local MouseLockAvailable = devAllowsMouseLock
+ and userHasMouseLockModeEnabled
+ and not userHasClickToMoveEnabled
+ and not devMovementModeIsScriptable
+
+ return MouseLockAvailable
+end
+
+------------------------------------------------------------------------
+
+local PlayerState = {}
+do
+ local mouseBehavior
+ local mouseIconEnabled
+ local cameraType
+ local cameraFocus
+ local cameraCFrame
+ local cameraFieldOfView
+ local screenGuis = {}
+ local coreGuis = {
+ Backpack = true,
+ Chat = true,
+ Health = true,
+ PlayerList = true,
+ }
+ local setCores = {
+ BadgesNotificationsActive = true,
+ PointsNotificationsActive = true,
+ }
+
+ -- Save state and set up for freecam
+ function PlayerState.Push()
+ for name in pairs(coreGuis) do
+ coreGuis[name] = StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType[name])
+ StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], false)
+ end
+ for name in pairs(setCores) do
+ setCores[name] = StarterGui:GetCore(name)
+ StarterGui:SetCore(name, false)
+ end
+ local playergui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
+ if playergui then
+ for _, gui in pairs(playergui:GetChildren()) do
+ if gui:IsA("ScreenGui") and gui.Enabled then
+ screenGuis[#screenGuis + 1] = gui
+ gui.Enabled = false
+ end
+ end
+ if FFlagUserFixFreecamGuiChangeVisibility then
+ playergui.ChildAdded:Connect(function(child)
+ if child:IsA("ScreenGui") and child.Enabled then
+ screenGuis[#screenGuis + 1] = child
+ child.Enabled = false
+ end
+ end)
+ end
+ end
+
+ cameraFieldOfView = Camera.FieldOfView
+ Camera.FieldOfView = 70
+
+ cameraType = Camera.CameraType
+ Camera.CameraType = Enum.CameraType.Custom
+
+ cameraCFrame = Camera.CFrame
+ cameraFocus = Camera.Focus
+
+ mouseIconEnabled = UserInputService.MouseIconEnabled
+ UserInputService.MouseIconEnabled = false
+
+ if FFlagUserExitFreecamBreaksWithShiftlock and CheckMouseLockAvailability() then
+ mouseBehavior = Enum.MouseBehavior.Default
+ else
+ mouseBehavior = UserInputService.MouseBehavior
+ end
+ UserInputService.MouseBehavior = Enum.MouseBehavior.Default
+ end
+
+ -- Restore state
+ function PlayerState.Pop()
+ for name, isEnabled in pairs(coreGuis) do
+ StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType[name], isEnabled)
+ end
+ for name, isEnabled in pairs(setCores) do
+ StarterGui:SetCore(name, isEnabled)
+ end
+ for _, gui in pairs(screenGuis) do
+ if gui.Parent then
+ gui.Enabled = true
+ end
+ end
+ if FFlagUserFixFreecamGuiChangeVisibility then
+ screenGuis = {}
+ end
+
+ Camera.FieldOfView = cameraFieldOfView
+ cameraFieldOfView = nil
+
+ Camera.CameraType = cameraType
+ cameraType = nil
+
+ Camera.CFrame = cameraCFrame
+ cameraCFrame = nil
+
+ Camera.Focus = cameraFocus
+ cameraFocus = nil
+
+ UserInputService.MouseIconEnabled = mouseIconEnabled
+ mouseIconEnabled = nil
+
+ UserInputService.MouseBehavior = mouseBehavior
+ mouseBehavior = nil
+ end
+end
+
+local function StartFreecam()
+ if not FFlagUserFreecamGuiDestabilization then
+ if FFlagUserShowGuiHideToggles then
+ script:SetAttribute(FREECAM_ENABLED_ATTRIBUTE_NAME, true)
+ end
+ end
+
+ local cameraCFrame = Camera.CFrame
+ if FFlagUserFreecamTiltControl then
+ cameraRot = Vector3.new(cameraCFrame:toEulerAnglesYXZ())
+ else
+ cameraRot = Vector2.new(cameraCFrame:toEulerAnglesYXZ())
+ end
+ cameraPos = cameraCFrame.p
+ cameraFov = Camera.FieldOfView
+
+ velSpring:Reset(Vector3.new())
+ panSpring:Reset(Vector2.new())
+ fovSpring:Reset(0)
+ if FFlagUserFreecamTiltControl then
+ rollSpring:Reset(0)
+ end
+
+ if FFlagUserFreecamSmoothnessControl then
+ VEL_STIFFNESS = 1.5
+ PAN_STIFFNESS = 1.0
+ FOV_STIFFNESS = 4.0
+ ROLL_STIFFNESS = 1.0
+ end
+
+ PlayerState.Push()
+
+ if FFlagUserFreecamDepthOfFieldEffect then
+ if not FreecamDepthOfField or not FreecamDepthOfField.Parent then
+ FreecamDepthOfField = Instance.new("DepthOfFieldEffect")
+ FreecamDepthOfField.Enabled = false
+ FreecamDepthOfField.Name = "FreecamDepthOfField"
+ FreecamDepthOfField.Parent = Camera
+ end
+ end
+
+ RunService:BindToRenderStep("Freecam", Enum.RenderPriority.Camera.Value, StepFreecam)
+ Input.StartCapture()
+end
+
+local function StopFreecam()
+ if not FFlagUserFreecamGuiDestabilization then
+ if FFlagUserShowGuiHideToggles then
+ script:SetAttribute(FREECAM_ENABLED_ATTRIBUTE_NAME, false)
+ end
+ end
+
+ if FFlagUserFreecamDepthOfFieldEffect then
+ if FreecamDepthOfField and FreecamDepthOfField.Parent then
+ if FreecamDepthOfField.Enabled then
+ for _, effect in ipairs(postEffects) do
+ if effect.Parent then
+ effect.Enabled = true
+ end
+ end
+ postEffects = {}
+ end
+ FreecamDepthOfField.Enabled = false
+ end
+ end
+
+ Input.StopCapture()
+ RunService:UnbindFromRenderStep("Freecam")
+ PlayerState.Pop()
+end
+
+------------------------------------------------------------------------
+
+do
+ local enabled = false
+
+ local function ToggleFreecam()
+ if enabled then
+ StopFreecam()
+ else
+ StartFreecam()
+ end
+ enabled = not enabled
+ if FFlagUserFreecamGuiDestabilization then
+ script:SetAttribute(FREECAM_ENABLED_ATTRIBUTE_NAME, enabled)
+ end
+ end
+
+ local function CheckMacro(macro)
+ for i = 1, #macro - 1 do
+ if not UserInputService:IsKeyDown(macro[i]) then
+ return
+ end
+ end
+ ToggleFreecam()
+ end
+
+ local function HandleActivationInput(action, state, input)
+ if state == Enum.UserInputState.Begin then
+ if input.KeyCode == FREECAM_MACRO_KB[#FREECAM_MACRO_KB] then
+ CheckMacro(FREECAM_MACRO_KB)
+ end
+
+ if input.KeyCode == Enum.KeyCode.F or input.KeyCode == Enum.KeyCode.DPadLeft then
+ ToggleFreecam()
+ end
+ end
+
+ return Enum.ContextActionResult.Pass
+ end
+
+ ContextActionService:BindActionAtPriority(
+ "FreecamToggle",
+ HandleActivationInput,
+ false,
+ TOGGLE_INPUT_PRIORITY,
+ FREECAM_MACRO_KB[#FREECAM_MACRO_KB]
+ )
+
+ ContextActionService:BindActionAtPriority("FreecamToggleDPAD", HandleActivationInput, false, TOGGLE_INPUT_PRIORITY, Enum.KeyCode.DPadLeft)
+
+ if FFlagUserFreecamGuiDestabilization or FFlagUserShowGuiHideToggles then
+ script:SetAttribute(FREECAM_ENABLED_ATTRIBUTE_NAME, enabled)
+ script:GetAttributeChangedSignal(FREECAM_ENABLED_ATTRIBUTE_NAME):Connect(function()
+ local attributeValue = script:GetAttribute(FREECAM_ENABLED_ATTRIBUTE_NAME)
+
+ if typeof(attributeValue) ~= "boolean" then
+ script:SetAttribute(FREECAM_ENABLED_ATTRIBUTE_NAME, enabled)
+ return
+ end
+
+ -- If the attribute's value and `enabled` var don't match, pick attribute value as
+ -- source of truth
+ if attributeValue ~= enabled then
+ if attributeValue then
+ StartFreecam()
+ enabled = true
+ else
+ StopFreecam()
+ enabled = false
+ end
+ end
+ end)
+ end
+
+ RF.OnClientInvoke = function(a, b, c)
+ if a == "Disable" and enabled then
+ enabled = false
+ StopFreecam()
+ end
+
+ if a == "Enable" and not enabled then
+ enabled = true
+ StartFreecam()
+ end
+
+ if a == "Toggle" then
+ ToggleFreecam()
+ end
+
+ if a == "End" or a == "Stop" then
+ RF.OnClientInvoke = nil
+ Debris:AddItem(RF, 0.5)
+ ContextActionService:UnbindAction("FreecamToggle")
+ ContextActionService:UnbindAction("FreecamToggle2")
+ ContextActionService:UnbindAction("FreecamToggleDPAD")
+ if enabled then -- Had to add this check because it would break your camera if it wasnt here. Not sure why.
+ enabled = false
+ StopFreecam()
+ end
+ end
+ end
+end
diff --git a/MainModule/Server/Dependencies/Assets/Freecam/Remote.model.json b/MainModule/Server/Dependencies/Assets/Freecam/Remote.model.json
new file mode 100644
index 0000000000..4834e8a4a9
--- /dev/null
+++ b/MainModule/Server/Dependencies/Assets/Freecam/Remote.model.json
@@ -0,0 +1,3 @@
+{
+ "ClassName": "RemoteFunction"
+}
\ No newline at end of file
diff --git a/MainModule/Server/Dependencies/Assets/Freecam/init.meta.json b/MainModule/Server/Dependencies/Assets/Freecam/init.meta.json
new file mode 100644
index 0000000000..eadf81a19c
--- /dev/null
+++ b/MainModule/Server/Dependencies/Assets/Freecam/init.meta.json
@@ -0,0 +1,3 @@
+{
+ "className": "ScreenGui"
+}
\ No newline at end of file
diff --git a/MainModule/Server/Dependencies/DefaultSettings.luau b/MainModule/Server/Dependencies/DefaultSettings.luau
index d3eceb87d0..b3b7eb4d7e 100644
--- a/MainModule/Server/Dependencies/DefaultSettings.luau
+++ b/MainModule/Server/Dependencies/DefaultSettings.luau
@@ -61,8 +61,9 @@ local descs = {}; --// Contains settings descriptions
If I wanted to make it so rank 134 in group 1029934 and BobJenkins123 had mod admin I would do
settings.Moderators = {"Group:1029943:134", "BobJenkins123"}
-
- I was going to change the admin rank stuff but I figured it would confuse people too much, so I left it as mods/admins/HeadAdmins ;p
+ !NOTE! When adding a group to a table, you may be tempted to replace the word Group with the name of your group – DON'T.
+ The group name is IRRELEVANT! If one's group was named 2Drool4School and it had the ID 2847031, the correct form is {"Group:2847031"}
+ and not {"2Drool4School:2847031"}
--// Admins
@@ -140,14 +141,13 @@ settings.HideScript = true -- When the game starts the Adonis_Loader model
settings.DataStore = "Adonis_1" -- DataStore the script will use for saving data; Changing this will lose any saved data
settings.DataStoreKey = "CHANGE_THIS" -- CHANGE THIS TO ANYTHING RANDOM! Key used to encrypt all datastore entries; Changing this will lose any saved data
settings.DataStoreEnabled = true -- Disable if you don't want to load settings and admins from the datastore; PlayerData will still save
-settings.LocalDatastore = false -- If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers
+settings.LocalDatastore = false -- If this is turned on, a mock DataStore will forcibly be used instead and shall never save across servers
-settings.Storage = game:GetService("ServerStorage") -- Where things like tools are stored
-settings.RecursiveTools = false -- Whether tools that are included in sub-containers within settings.Storage will be available via the ;give command (useful if your tools are organized into multiple folders)
+settings.Storage = game:GetService("ServerStorage") -- Where things like tools are stored
+settings.RecursiveTools = false -- Whether tools that are included in sub-containers within settings.Storage will be available via the ;give command (useful if your tools are organized into multiple folders)
settings.Theme = "Default" -- UI theme;
settings.MobileTheme = "Mobilius" -- Theme to use on mobile devices; Some UI elements are disabled
-
--[[
**HOW TO ADD ADMINISTRATORS:**
Below are the administrator permission levels/ranks (Mods, Admins, HeadAdmins, Creators, StuffYouAdd, etc)
@@ -157,7 +157,7 @@ settings.MobileTheme = "Mobilius" -- Theme to use on mobile devices; Some UI el
settings.Ranks = {
["Moderators"] = {
Level = 100;
- Users = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID"; "Subscription:SubscriptionId";}
+ Users = {"Username"; "Username:UserId"; UserId; "Group:GroupId:GroupRank"; "Group:GroupId"; "Item:ItemID"; "GamePass:GamePassID";}
}
}
@@ -210,6 +210,7 @@ settings.Aliases = {
[";examplealias "] = ";ff | ;fling | ;fire " --// Order arguments appear in alias string determines their required order in the command message when ran later
};
+--// Use the below table to define pre-set cameras
settings.Cameras = {
--[[
"Camera Name" would be the name of your camera
@@ -283,17 +284,18 @@ settings.CommandCooldowns = {
]]
}
-settings.FunCommands = true -- Are fun commands enabled?
-settings.PlayerCommands = true -- Are player-level utility commands enabled?
-settings.AgeRestrictedCommands = true -- Are age-locked commands enabled?
-settings.WarnDangerousCommand = false -- Do dangerous commands ask for confirmation?
-settings.CommandFeedback = false -- Should players be notified when commands with non-obvious effects are run on them?
-settings.CrossServerCommands = true -- Are commands which affect more than one server enabled?
-settings.ChatCommands = true -- If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands
-settings.CreatorPowers = true -- Gives me creator-level admin; This is strictly used for debugging; I can't debug without full access to the script
-settings.CodeExecution = true -- Enables the use of code execution in Adonis; Scripting related (such as ;s) and a few other commands require this
-settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command
-settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false.
+settings.FunCommands = true -- Are fun commands enabled?
+settings.PlayerCommands = true -- Are player-level utility commands enabled?
+settings.AgeRestrictedCommands = true -- Are age-locked commands enabled?
+settings.WarnDangerousCommand = false -- Do dangerous commands ask for confirmation?
+settings.CommandFeedback = false -- Should players be notified when commands with non-obvious effects are run on them?
+settings.CrossServerCommands = true -- Are commands which affect more than one server enabled?
+settings.ChatCommands = true -- If false you will not be able to run commands via the chat; Instead, you MUST use the console or you will be unable to run commands
+settings.CreatorPowers = true -- Gives me creator-level admin; This is strictly used for debugging; I can't debug without full access to the script
+settings.CodeExecution = false -- Enables the use of code execution in Adonis. Scripting related (such as ;s) and a few other commands require this
+settings.SilentCommandDenials = false -- If true, there will be no differences between the error messages shown when a user enters an invalid command and when they have insufficient permissions for the command
+settings.OverrideChatCallbacks = true -- If the TextChatService ShouldDeliverCallbacks of all channels are overridden by Adonis on load. Required for slowmode. Mutes use a CanSend method to mute when this is set to false.
+settings.ChatCreateRobloxCommands = false -- Whether "/" commands for Roblox should get created in new Chat
settings.BanMessage = "Banned" -- Message shown to banned users upon kick
settings.LockMessage = "Not Whitelisted" -- Message shown to people when they are kicked while the game is ;slocked
@@ -604,7 +606,6 @@ order = {
"AutoBackup";
" ";
"PlayerList";
- " ";
"Console";
"Console_AdminsOnly";
" ";
diff --git a/MainModule/Shared/Changelog.luau b/MainModule/Shared/Changelog.luau
index 507e227bba..969a430537 100644
--- a/MainModule/Shared/Changelog.luau
+++ b/MainModule/Shared/Changelog.luau
@@ -3,11 +3,13 @@ return {
"*Drag edges to expand*";
"*Report bugs/issues on our GitHub repository*";
"";
- "[v268 2025-06-24 15:30 UTC] @Dimenpsyonal";
+ "[v268 2025-08-12 06:59 UTC] @Dimenpsyonal";
"(Git/fxeP1) Fix first joined player DS ranks (#1918)";
"(Git/fxeP1) Fix security related to Client G_API (#1919)";
"(Git/ccuser44) Fix donor cape not updating from UserPanel (#1926)";
"(Git/ccuser44) Make donor status updating asynchronous (#1922)";
+ "(Git/fxeP1) Re-add ChatCreateRobloxCommands (#1946)";
+ "(Git/kaiserandaxl) Fix Resize command Breaking (#1936)";
"";
"[Patch v267.1 2025-06-07 18:19 UTC] @Dimenpsyonal";
"(Git/kaiserandaxl) Fix updateStatus for Capes in UserPanel (#1914)";
diff --git a/build.sh b/build.sh
index 5da0cb392a..9fd10aa324 100644
--- a/build.sh
+++ b/build.sh
@@ -1,10 +1,10 @@
#!/bin/bash
-printf "Updating Roblox standard library"
+echo "Updating Roblox standard library"
selene generate-roblox-std
-printf "Checking for lint errors from ./Loader and ./MainModule"
+echo "Checking for lint errors from ./Loader and ./MainModule"
selene ./Loader ./MainModule
-printf "Running rojo build -o Adonis.rbxl"
+echo "Running rojo build -o Adonis.rbxl"
rojo build -o Adonis.rbxl