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