Created
July 26, 2026 03:13
-
-
Save DuyNgao2306/827f8258c6c0d68ecc1a982249f6aca0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- [[ VISUAL AUTO CLICKER - ULTRA PC & MOBILE CLICK FIX (V0.1) ]] -- | |
| local Players = game:GetService("Players") | |
| local UserInputService = game:GetService("UserInputService") | |
| local VirtualInputManager = game:GetService("VirtualInputManager") | |
| local GuiService = game:GetService("GuiService") | |
| local HttpService = game:GetService("HttpService") | |
| local LocalPlayer = Players.LocalPlayer | |
| local PlayerGui = LocalPlayer:WaitForChild("PlayerGui", 10) | |
| if not PlayerGui then return end | |
| math.randomseed(os.time()) | |
| if PlayerGui:FindFirstChild("MacroSystemGui") then | |
| PlayerGui.MacroSystemGui:Destroy() | |
| end | |
| local pointsData = {} | |
| local MAX_CLICKS = 100 | |
| local currentMode = "None" | |
| local isRunning = false | |
| local isMinimized = false | |
| local connections = {} | |
| local currentlyEditingPoint = nil | |
| local runThread = nil | |
| -- FORWARD DECLARATIONS | |
| local createWaypoint | |
| local setMode | |
| -- SAFE TABLE CLEAR HELPER | |
| local function safeClear(t) | |
| if table.clear then | |
| table.clear(t) | |
| else | |
| for k in pairs(t) do | |
| t[k] = nil | |
| end | |
| end | |
| end | |
| -- CHECK FILE SYSTEM SUPPORT | |
| local hasFileSupport = (writefile and readfile and isfolder and makefolder) | |
| local folderName = "VisualMacroSlots" | |
| if hasFileSupport then | |
| pcall(function() | |
| if not isfolder(folderName) then | |
| makefolder(folderName) | |
| end | |
| end) | |
| end | |
| -- 1. MAIN GUI CREATION | |
| local ScreenGui = Instance.new("ScreenGui") | |
| ScreenGui.Name = "MacroSystemGui" | |
| ScreenGui.ResetOnSpawn = false | |
| ScreenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling | |
| ScreenGui.DisplayOrder = 999 | |
| ScreenGui.Parent = PlayerGui | |
| local PointsFolder = Instance.new("Folder") | |
| PointsFolder.Name = "PointsFolder" | |
| PointsFolder.Parent = ScreenGui | |
| local MainFrame = Instance.new("Frame") | |
| MainFrame.Name = "MainFrame" | |
| MainFrame.Size = UDim2.new(0, 310, 0, 480) | |
| MainFrame.Position = UDim2.new(0.5, -155, 0.3, 0) | |
| MainFrame.BackgroundColor3 = Color3.fromRGB(25, 27, 38) | |
| MainFrame.BorderSizePixel = 0 | |
| MainFrame.Active = true | |
| MainFrame.Parent = ScreenGui | |
| local UICorner = Instance.new("UICorner") | |
| UICorner.CornerRadius = UDim.new(0, 10) | |
| UICorner.Parent = MainFrame | |
| local UIStroke = Instance.new("UIStroke") | |
| UIStroke.Color = Color3.fromRGB(60, 65, 85) | |
| UIStroke.Thickness = 1.5 | |
| UIStroke.Parent = MainFrame | |
| local Header = Instance.new("Frame") | |
| Header.Size = UDim2.new(1, 0, 0, 38) | |
| Header.BackgroundColor3 = Color3.fromRGB(35, 38, 52) | |
| Header.BorderSizePixel = 0 | |
| Header.Parent = MainFrame | |
| local HeaderCorner = Instance.new("UICorner") | |
| HeaderCorner.CornerRadius = UDim.new(0, 10) | |
| HeaderCorner.Parent = Header | |
| local Title = Instance.new("TextLabel") | |
| Title.Size = UDim2.new(1, -80, 1, 0) | |
| Title.Position = UDim2.new(0, 12, 0, 0) | |
| Title.BackgroundTransparency = 1 | |
| Title.Text = "✨ VISUAL AUTO CLICKER (V0.1)" | |
| Title.TextColor3 = Color3.fromRGB(255, 255, 255) | |
| Title.TextSize = 13 | |
| Title.Font = Enum.Font.GothamBold | |
| Title.TextXAlignment = Enum.TextXAlignment.Left | |
| Title.Parent = Header | |
| local CloseBtn = Instance.new("TextButton") | |
| CloseBtn.Size = UDim2.new(0, 30, 0, 30) | |
| CloseBtn.Position = UDim2.new(1, -5, 0.5, 0) | |
| CloseBtn.AnchorPoint = Vector2.new(1, 0.5) | |
| CloseBtn.BackgroundTransparency = 1 | |
| CloseBtn.Text = "✕" | |
| CloseBtn.TextColor3 = Color3.fromRGB(255, 71, 87) | |
| CloseBtn.TextSize = 16 | |
| CloseBtn.Font = Enum.Font.GothamBold | |
| CloseBtn.ZIndex = 10 | |
| CloseBtn.Parent = Header | |
| local MinimizeBtn = Instance.new("TextButton") | |
| MinimizeBtn.Size = UDim2.new(0, 30, 0, 30) | |
| MinimizeBtn.Position = UDim2.new(1, -38, 0.5, 0) | |
| MinimizeBtn.AnchorPoint = Vector2.new(1, 0.5) | |
| MinimizeBtn.BackgroundTransparency = 1 | |
| MinimizeBtn.Text = "🗕" | |
| MinimizeBtn.TextColor3 = Color3.fromRGB(255, 234, 167) | |
| MinimizeBtn.TextSize = 16 | |
| MinimizeBtn.Font = Enum.Font.GothamBold | |
| MinimizeBtn.ZIndex = 10 | |
| MinimizeBtn.Parent = Header | |
| local StatusLabel = Instance.new("TextLabel") | |
| StatusLabel.Size = UDim2.new(1, -24, 0, 20) | |
| StatusLabel.Position = UDim2.new(0, 12, 0, 45) | |
| StatusLabel.BackgroundTransparency = 1 | |
| StatusLabel.Text = "Status: Resting" | |
| StatusLabel.TextColor3 = Color3.fromRGB(180, 185, 200) | |
| StatusLabel.TextSize = 13 | |
| StatusLabel.Font = Enum.Font.GothamMedium | |
| StatusLabel.TextXAlignment = Enum.TextXAlignment.Left | |
| StatusLabel.Parent = MainFrame | |
| -- JSON INBOX | |
| local JsonInbox = Instance.new("TextBox") | |
| JsonInbox.Name = "JsonInbox" | |
| JsonInbox.Size = UDim2.new(1, -24, 0, 45) | |
| JsonInbox.Position = UDim2.new(0, 12, 0, 70) | |
| JsonInbox.BackgroundColor3 = Color3.fromRGB(20, 22, 30) | |
| JsonInbox.TextColor3 = Color3.fromRGB(120, 224, 143) | |
| JsonInbox.TextSize = 10 | |
| JsonInbox.Font = Enum.Font.Code | |
| JsonInbox.Text = "" | |
| JsonInbox.PlaceholderText = "Saved JSON Inbox (Tap/Click to copy)..." | |
| JsonInbox.ClearTextOnFocus = false | |
| JsonInbox.TextEditable = true | |
| JsonInbox.MultiLine = true | |
| JsonInbox.TextWrapped = true | |
| JsonInbox.Parent = MainFrame | |
| Instance.new("UICorner", JsonInbox).CornerRadius = UDim.new(0, 6) | |
| local InboxStroke = Instance.new("UIStroke") | |
| InboxStroke.Color = Color3.fromRGB(50, 55, 75) | |
| InboxStroke.Thickness = 1 | |
| InboxStroke.Parent = JsonInbox | |
| local BtnContainer = Instance.new("Frame") | |
| BtnContainer.Size = UDim2.new(1, -24, 1, -170) | |
| BtnContainer.Position = UDim2.new(0, 12, 0, 122) | |
| BtnContainer.BackgroundTransparency = 1 | |
| BtnContainer.Parent = MainFrame | |
| local GridLayout = Instance.new("UIGridLayout") | |
| GridLayout.CellSize = UDim2.new(0.5, -5, 0, 35) | |
| GridLayout.CellPadding = UDim2.new(0, 10, 0, 8) | |
| GridLayout.SortOrder = Enum.SortOrder.LayoutOrder | |
| GridLayout.Parent = BtnContainer | |
| local function createButton(name, text, color, order) | |
| local btn = Instance.new("TextButton") | |
| btn.Name = name | |
| btn.BackgroundColor3 = color | |
| btn.Text = text | |
| btn.TextColor3 = Color3.fromRGB(255, 255, 255) | |
| btn.Font = Enum.Font.GothamBold | |
| btn.TextSize = 12 | |
| btn.LayoutOrder = order | |
| btn.Parent = BtnContainer | |
| local corner = Instance.new("UICorner") | |
| corner.CornerRadius = UDim.new(0, 6) | |
| corner.Parent = btn | |
| return btn | |
| end | |
| local BtnAdd = createButton("BtnAdd", "➕ Add Point", Color3.fromRGB(108, 92, 231), 1) | |
| local BtnMove = createButton("BtnMove", "🖐️ Move Point", Color3.fromRGB(225, 112, 85), 2) | |
| local BtnTime = createButton("BtnTime", "⏱️ Edit Time", Color3.fromRGB(9, 132, 227), 3) | |
| local BtnDelOne = createButton("BtnDelOne", "❌ Delete One", Color3.fromRGB(214, 48, 49), 4) | |
| local BtnSave = createButton("BtnSave", "💾 Save Script", Color3.fromRGB(0, 206, 201), 5) | |
| local BtnLoad = createButton("BtnLoad", "📥 Load Script", Color3.fromRGB(46, 204, 113), 6) | |
| local BtnDataStore = createButton("BtnDataStore", "📦 Data Store", Color3.fromRGB(238, 82, 83), 7) | |
| local BtnClear = createButton("BtnClear", "🗑️ Clear All", Color3.fromRGB(116, 125, 140), 8) | |
| local BtnStart = createButton("BtnStart", "▶️ START MACRO", Color3.fromRGB(0, 184, 148), 9) | |
| BtnStart.Size = UDim2.new(1, 0, 0, 40) | |
| GridLayout.FillDirectionMaxCells = 2 | |
| -- 2. TIME POPUP | |
| local TimePopup = Instance.new("Frame") | |
| TimePopup.Size = UDim2.new(0, 200, 0, 120) | |
| TimePopup.Position = UDim2.new(0.5, 0, 0.5, 0) | |
| TimePopup.AnchorPoint = Vector2.new(0.5, 0.5) | |
| TimePopup.BackgroundColor3 = Color3.fromRGB(45, 52, 54) | |
| TimePopup.Visible = false | |
| TimePopup.ZIndex = 50 | |
| TimePopup.Parent = ScreenGui | |
| Instance.new("UICorner", TimePopup).CornerRadius = UDim.new(0, 10) | |
| local PopupLabel = Instance.new("TextLabel") | |
| PopupLabel.Size = UDim2.new(1, 0, 0, 30); PopupLabel.Position = UDim2.new(0,0,0,10); PopupLabel.BackgroundTransparency = 1 | |
| PopupLabel.Text = "Enter delay time (sec):" ; PopupLabel.TextColor3 = Color3.new(1,1,1); PopupLabel.Font = Enum.Font.GothamBold; PopupLabel.Parent = TimePopup | |
| local TimeInput = Instance.new("TextBox") | |
| TimeInput.Size = UDim2.new(0.8, 0, 0, 30); TimeInput.Position = UDim2.new(0.1, 0, 0, 40); TimeInput.BackgroundColor3 = Color3.fromRGB(20,20,20); TimeInput.TextColor3 = Color3.new(1,1,1) | |
| TimeInput.Text = "0.1"; TimeInput.Font = Enum.Font.GothamMedium; TimeInput.Parent = TimePopup | |
| local PopupSave = Instance.new("TextButton") | |
| PopupSave.Size = UDim2.new(0.8, 0, 0, 30); PopupSave.Position = UDim2.new(0.1, 0, 0, 80); PopupSave.BackgroundColor3 = Color3.fromRGB(0, 184, 148); PopupSave.Text = "SAVE"; PopupSave.TextColor3 = Color3.new(1,1,1); PopupSave.Font = Enum.Font.GothamBold; PopupSave.Parent = TimePopup; Instance.new("UICorner", PopupSave) | |
| -- 2.1. LOAD POPUP | |
| local LoadPopup = Instance.new("Frame") | |
| LoadPopup.Size = UDim2.new(0, 240, 0, 150) | |
| LoadPopup.Position = UDim2.new(0.5, 0, 0.5, 0) | |
| LoadPopup.AnchorPoint = Vector2.new(0.5, 0.5) | |
| LoadPopup.BackgroundColor3 = Color3.fromRGB(45, 52, 54) | |
| LoadPopup.Visible = false | |
| LoadPopup.ZIndex = 50 | |
| LoadPopup.Parent = ScreenGui | |
| Instance.new("UICorner", LoadPopup).CornerRadius = UDim.new(0, 10) | |
| local LoadPopupLabel = Instance.new("TextLabel") | |
| LoadPopupLabel.Size = UDim2.new(1, 0, 0, 30); LoadPopupLabel.Position = UDim2.new(0, 0, 0, 10); LoadPopupLabel.BackgroundTransparency = 1 | |
| LoadPopupLabel.Text = "Paste JSON Script here:"; LoadPopupLabel.TextColor3 = Color3.new(1,1,1); LoadPopupLabel.Font = Enum.Font.GothamBold; LoadPopupLabel.TextSize = 12; LoadPopupLabel.Parent = LoadPopup | |
| local LoadInput = Instance.new("TextBox") | |
| LoadInput.Size = UDim2.new(0.85, 0, 0, 45); LoadInput.Position = UDim2.new(0.075, 0, 0, 45); LoadInput.BackgroundColor3 = Color3.fromRGB(20,20,20); LoadInput.TextColor3 = Color3.new(1,1,1) | |
| LoadInput.Text = ""; LoadInput.PlaceholderText = "Paste JSON string here..."; LoadInput.Font = Enum.Font.GothamMedium; LoadInput.TextSize = 10; LoadInput.ClearTextOnFocus = false; LoadInput.Parent = LoadPopup | |
| Instance.new("UICorner", LoadInput).CornerRadius = UDim.new(0, 6) | |
| local PopupLoadBtn = Instance.new("TextButton") | |
| PopupLoadBtn.Size = UDim2.new(0.85, 0, 0, 30); PopupLoadBtn.Position = UDim2.new(0.075, 0, 0, 100); PopupLoadBtn.BackgroundColor3 = Color3.fromRGB(46, 204, 113) | |
| PopupLoadBtn.Text = "CONFIRM LOAD"; PopupLoadBtn.TextColor3 = Color3.new(1,1,1); PopupLoadBtn.Font = Enum.Font.GothamBold; PopupLoadBtn.TextSize = 12; PopupLoadBtn.Parent = LoadPopup | |
| Instance.new("UICorner", PopupLoadBtn).CornerRadius = UDim.new(0, 6) | |
| -- 2.2. DATA STORE POPUP | |
| local DataStorePopup = Instance.new("Frame") | |
| DataStorePopup.Size = UDim2.new(0, 280, 0, 260) | |
| DataStorePopup.Position = UDim2.new(0.5, 0, 0.5, 0) | |
| DataStorePopup.AnchorPoint = Vector2.new(0.5, 0.5) | |
| DataStorePopup.BackgroundColor3 = Color3.fromRGB(35, 38, 52) | |
| DataStorePopup.Visible = false | |
| DataStorePopup.ZIndex = 60 | |
| DataStorePopup.Parent = ScreenGui | |
| Instance.new("UICorner", DataStorePopup).CornerRadius = UDim.new(0, 10) | |
| Instance.new("UIStroke", DataStorePopup).Color = Color3.fromRGB(80, 90, 120) | |
| local DSHeader = Instance.new("TextLabel") | |
| DSHeader.Size = UDim2.new(1, 0, 0, 35) | |
| DSHeader.BackgroundTransparency = 1 | |
| DSHeader.Text = "📦 JSON Data Store (5 Slots)" | |
| DSHeader.TextColor3 = Color3.fromRGB(255, 255, 255) | |
| DSHeader.Font = Enum.Font.GothamBold | |
| DSHeader.TextSize = 12 | |
| DSHeader.Parent = DataStorePopup | |
| local DSCloseBtn = Instance.new("TextButton") | |
| DSCloseBtn.Size = UDim2.new(0, 30, 0, 30) | |
| DSCloseBtn.Position = UDim2.new(1, -5, 0, 2) | |
| DSCloseBtn.BackgroundTransparency = 1 | |
| DSCloseBtn.Text = "✕" | |
| DSCloseBtn.TextColor3 = Color3.fromRGB(255, 71, 87) | |
| DSCloseBtn.TextSize = 14 | |
| DSCloseBtn.Font = Enum.Font.GothamBold | |
| DSCloseBtn.Parent = DataStorePopup | |
| local SlotContainer = Instance.new("ScrollingFrame") | |
| SlotContainer.Size = UDim2.new(1, -16, 1, -45) | |
| SlotContainer.Position = UDim2.new(0, 8, 0, 38) | |
| SlotContainer.BackgroundTransparency = 1 | |
| SlotContainer.BorderSizePixel = 0 | |
| SlotContainer.CanvasSize = UDim2.new(0, 0, 0, 5 * 40 + 10) | |
| SlotContainer.ScrollBarThickness = 4 | |
| SlotContainer.Parent = DataStorePopup | |
| local UIListLayout = Instance.new("UIListLayout") | |
| UIListLayout.SortOrder = Enum.SortOrder.LayoutOrder | |
| UIListLayout.Padding = UDim.new(0, 6) | |
| UIListLayout.Parent = SlotContainer | |
| local slotRows = {} | |
| local function getSlotFilePath(slotIndex) | |
| return folderName .. "/slot_" .. slotIndex .. ".json" | |
| end | |
| local function refreshSlotUI() | |
| if not hasFileSupport then return end | |
| for i = 1, 5 do | |
| local filePath = getSlotFilePath(i) | |
| local hasData = false | |
| pcall(function() | |
| if isfile and isfile(filePath) then | |
| local content = readfile(filePath) | |
| if content and content ~= "" then | |
| hasData = true | |
| end | |
| end | |
| end) | |
| if slotRows[i] then | |
| if hasData then | |
| slotRows[i].label.Text = "Slot " .. i .. " [Saved]" | |
| slotRows[i].label.TextColor3 = Color3.fromRGB(120, 224, 143) | |
| else | |
| slotRows[i].label.Text = "Slot " .. i .. " [Empty]" | |
| slotRows[i].label.TextColor3 = Color3.fromRGB(180, 185, 200) | |
| end | |
| end | |
| end | |
| end | |
| for i = 1, 5 do | |
| local row = Instance.new("Frame") | |
| row.Size = UDim2.new(1, 0, 0, 34) | |
| row.BackgroundColor3 = Color3.fromRGB(20, 22, 30) | |
| row.LayoutOrder = i | |
| row.Parent = SlotContainer | |
| Instance.new("UICorner", row).CornerRadius = UDim.new(0, 6) | |
| local label = Instance.new("TextLabel") | |
| label.Size = UDim2.new(0, 75, 1, 0) | |
| label.Position = UDim2.new(0, 6, 0, 0) | |
| label.BackgroundTransparency = 1 | |
| label.Text = "Slot " .. i .. " [Empty]" | |
| label.TextColor3 = Color3.fromRGB(180, 185, 200) | |
| label.Font = Enum.Font.GothamBold | |
| label.TextSize = 11 | |
| label.TextXAlignment = Enum.TextXAlignment.Left | |
| label.Parent = row | |
| local saveBtn = Instance.new("TextButton") | |
| saveBtn.Size = UDim2.new(0, 48, 0, 24) | |
| saveBtn.Position = UDim2.new(1, -156, 0.5, -12) | |
| saveBtn.BackgroundColor3 = Color3.fromRGB(0, 206, 201) | |
| saveBtn.Text = "Save" | |
| saveBtn.TextColor3 = Color3.fromRGB(255, 255, 255) | |
| saveBtn.Font = Enum.Font.GothamBold | |
| saveBtn.TextSize = 10 | |
| saveBtn.Parent = row | |
| Instance.new("UICorner", saveBtn).CornerRadius = UDim.new(0, 4) | |
| local loadBtn = Instance.new("TextButton") | |
| loadBtn.Size = UDim2.new(0, 48, 0, 24) | |
| loadBtn.Position = UDim2.new(1, -104, 0.5, -12) | |
| loadBtn.BackgroundColor3 = Color3.fromRGB(46, 204, 113) | |
| loadBtn.Text = "Load" | |
| loadBtn.TextColor3 = Color3.fromRGB(255, 255, 255) | |
| loadBtn.Font = Enum.Font.GothamBold | |
| loadBtn.TextSize = 10 | |
| loadBtn.Parent = row | |
| Instance.new("UICorner", loadBtn).CornerRadius = UDim.new(0, 4) | |
| local delBtn = Instance.new("TextButton") | |
| delBtn.Size = UDim2.new(0, 48, 0, 24) | |
| delBtn.Position = UDim2.new(1, -52, 0.5, -12) | |
| delBtn.BackgroundColor3 = Color3.fromRGB(214, 48, 49) | |
| delBtn.Text = "Del" | |
| delBtn.TextColor3 = Color3.fromRGB(255, 255, 255) | |
| delBtn.Font = Enum.Font.GothamBold | |
| delBtn.TextSize = 10 | |
| delBtn.Parent = row | |
| Instance.new("UICorner", delBtn).CornerRadius = UDim.new(0, 4) | |
| slotRows[i] = {label = label} | |
| saveBtn.Activated:Connect(function() | |
| if not hasFileSupport then | |
| StatusLabel.Text = "Status: Executor doesn't support save!" | |
| return | |
| end | |
| if #pointsData == 0 then | |
| StatusLabel.Text = "Status: No points to save!" | |
| task.delay(2, function() if not isRunning then StatusLabel.Text = "Status: Resting" end end) | |
| return | |
| end | |
| local viewport = workspace.CurrentCamera.ViewportSize | |
| local exportTable = {} | |
| for _, data in ipairs(pointsData) do | |
| if data.frame and data.frame.Parent then | |
| local posX = data.frame.AbsolutePosition.X + (data.frame.AbsoluteSize.X / 2) | |
| local posY = data.frame.AbsolutePosition.Y + (data.frame.AbsoluteSize.Y / 2) | |
| table.insert(exportTable, {scaleX = posX / viewport.X, scaleY = posY / viewport.Y, delay = data.delay}) | |
| end | |
| end | |
| local success = pcall(function() | |
| local jsonString = HttpService:JSONEncode(exportTable) | |
| writefile(getSlotFilePath(i), jsonString) | |
| JsonInbox.Text = jsonString | |
| end) | |
| if success then | |
| refreshSlotUI() | |
| StatusLabel.Text = "Status: Saved to Slot " .. i .. "!" | |
| else | |
| StatusLabel.Text = "Status: Save error!" | |
| end | |
| task.delay(2, function() if not isRunning then StatusLabel.Text = "Status: Resting" end end) | |
| end) | |
| loadBtn.Activated:Connect(function() | |
| if isRunning then return end | |
| if not hasFileSupport then | |
| StatusLabel.Text = "Status: Executor doesn't support load!" | |
| return | |
| end | |
| local filePath = getSlotFilePath(i) | |
| local success = pcall(function() | |
| if isfile and isfile(filePath) then | |
| local rawText = readfile(filePath) | |
| if not rawText or rawText == "" then | |
| StatusLabel.Text = "Status: Slot " .. i .. " is empty!" | |
| return | |
| end | |
| local decodedData = HttpService:JSONDecode(rawText) | |
| if type(decodedData) == "table" and #decodedData > 0 then | |
| for _, data in ipairs(pointsData) do | |
| if data.frame then data.frame:Destroy() end | |
| end | |
| safeClear(pointsData) | |
| setMode("None") | |
| local viewport = workspace.CurrentCamera.ViewportSize | |
| for _, item in ipairs(decodedData) do | |
| local px, py | |
| if item.scaleX and item.scaleY then | |
| px = item.scaleX * viewport.X | |
| py = item.scaleY * viewport.Y | |
| elseif item.x and item.y then | |
| px = item.x | |
| py = item.y | |
| end | |
| if px and py then | |
| createWaypoint(px, py, item.delay or 0.1) | |
| end | |
| end | |
| JsonInbox.Text = rawText | |
| StatusLabel.Text = "Status: Loaded from Slot " .. i .. "!" | |
| else | |
| StatusLabel.Text = "Status: Invalid slot format!" | |
| end | |
| else | |
| StatusLabel.Text = "Status: Slot " .. i .. " is empty!" | |
| end | |
| end) | |
| if not success then | |
| StatusLabel.Text = "Status: Load error!" | |
| end | |
| DataStorePopup.Visible = false | |
| task.delay(2.5, function() | |
| if not isRunning then StatusLabel.Text = "Status: Resting" end | |
| end) | |
| end) | |
| delBtn.Activated:Connect(function() | |
| if not hasFileSupport then | |
| StatusLabel.Text = "Status: Executor doesn't support delete!" | |
| return | |
| end | |
| local filePath = getSlotFilePath(i) | |
| local success = pcall(function() | |
| if delfile and isfile and isfile(filePath) then | |
| delfile(filePath) | |
| end | |
| end) | |
| if success then | |
| refreshSlotUI() | |
| StatusLabel.Text = "Status: Deleted Slot " .. i .. "!" | |
| else | |
| StatusLabel.Text = "Status: Delete error or file missing!" | |
| end | |
| task.delay(2, function() if not isRunning then StatusLabel.Text = "Status: Resting" end end) | |
| end) | |
| end | |
| -- 3. MAIN UI DRAG SYSTEM | |
| local draggingUI, dragStartUI, startPosUI | |
| table.insert(connections, Header.InputBegan:Connect(function(input) | |
| if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then | |
| draggingUI = true; dragStartUI = input.Position; startPosUI = MainFrame.Position | |
| end | |
| end)) | |
| table.insert(connections, UserInputService.InputChanged:Connect(function(input) | |
| if draggingUI and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then | |
| local delta = input.Position - dragStartUI | |
| MainFrame.Position = UDim2.new(startPosUI.X.Scale, startPosUI.X.Offset + delta.X, startPosUI.Y.Scale, startPosUI.Y.Offset + delta.Y) | |
| end | |
| end)) | |
| table.insert(connections, UserInputService.InputEnded:Connect(function(input) | |
| if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then draggingUI = false end | |
| end)) | |
| MinimizeBtn.Activated:Connect(function() | |
| isMinimized = not isMinimized | |
| if isMinimized then | |
| MinimizeBtn.Text = "🗖" | |
| MainFrame.Size = UDim2.new(0, 310, 0, 38) | |
| BtnContainer.Visible = false | |
| StatusLabel.Visible = false | |
| JsonInbox.Visible = false | |
| TimePopup.Visible = false | |
| LoadPopup.Visible = false | |
| DataStorePopup.Visible = false | |
| else | |
| MinimizeBtn.Text = "🗕" | |
| MainFrame.Size = UDim2.new(0, 310, 0, 480) | |
| BtnContainer.Visible = true | |
| StatusLabel.Visible = true | |
| JsonInbox.Visible = true | |
| end | |
| end) | |
| local function isClickingOnMacroUI(clickPos) | |
| local frames = {MainFrame, TimePopup, LoadPopup, DataStorePopup} | |
| for _, frame in ipairs(frames) do | |
| if frame.Visible then | |
| local pos, size = frame.AbsolutePosition, frame.AbsoluteSize | |
| if clickPos.X >= pos.X and clickPos.X <= (pos.X + size.X) and clickPos.Y >= pos.Y and clickPos.Y <= (pos.Y + size.Y) then | |
| return true | |
| end | |
| end | |
| end | |
| return false | |
| end | |
| -- DEFINITION OF setMode | |
| function setMode(mode) | |
| if isRunning then return end | |
| currentMode = (currentMode == mode) and "None" or mode | |
| BtnAdd.BackgroundColor3 = (currentMode == "Add") and Color3.fromRGB(162, 155, 254) or Color3.fromRGB(108, 92, 231) | |
| BtnMove.BackgroundColor3 = (currentMode == "Move") and Color3.fromRGB(250, 177, 160) or Color3.fromRGB(225, 112, 85) | |
| BtnTime.BackgroundColor3 = (currentMode == "Time") and Color3.fromRGB(116, 185, 255) or Color3.fromRGB(9, 132, 227) | |
| BtnDelOne.BackgroundColor3 = (currentMode == "DeleteOne") and Color3.fromRGB(255, 107, 107) or Color3.fromRGB(214, 48, 49) | |
| TimePopup.Visible = false | |
| LoadPopup.Visible = false | |
| DataStorePopup.Visible = false | |
| if currentMode == "None" then StatusLabel.Text = "Status: Resting" | |
| elseif currentMode == "Add" then StatusLabel.Text = "Status: Click screen to place point" | |
| elseif currentMode == "Move" then StatusLabel.Text = "Status: Drag points to move" | |
| elseif currentMode == "Time" then StatusLabel.Text = "Status: Click point to edit time" | |
| elseif currentMode == "DeleteOne" then StatusLabel.Text = "Status: Click point to DELETE" end | |
| end | |
| local function refreshWaypointIndices() | |
| for index, data in ipairs(pointsData) do | |
| data.id = index | |
| if data.numLabel then | |
| data.numLabel.Text = tostring(index) | |
| end | |
| end | |
| end | |
| -- 4. WAYPOINT CREATION (DEFINITION) | |
| function createWaypoint(x, y, customDelay) | |
| if #pointsData >= MAX_CLICKS then return end | |
| local id = #pointsData + 1 | |
| local pointDelay = customDelay or 0.1 | |
| local Dot = Instance.new("Frame") | |
| Dot.Size = UDim2.new(0, 34, 0, 34) | |
| Dot.Position = UDim2.new(0, x, 0, y) | |
| Dot.AnchorPoint = Vector2.new(0.5, 0.5) | |
| Dot.BackgroundColor3 = Color3.fromRGB(255, 159, 67) | |
| Dot.BorderSizePixel = 0 | |
| Dot.ZIndex = 50 | |
| Dot.Parent = PointsFolder | |
| Instance.new("UICorner", Dot).CornerRadius = UDim.new(1, 0) | |
| local UIStrokeDot = Instance.new("UIStroke"); UIStrokeDot.Color = Color3.new(1,1,1); UIStrokeDot.Thickness = 2; UIStrokeDot.Parent = Dot | |
| local NumLabel = Instance.new("TextLabel"); NumLabel.Size = UDim2.new(1, 0, 1, 0); NumLabel.BackgroundTransparency = 1; NumLabel.Text = tostring(id); NumLabel.TextColor3 = Color3.new(1,1,1); NumLabel.Font = Enum.Font.GothamBold; NumLabel.TextSize = 16; NumLabel.Parent = Dot | |
| local TimeLabel = Instance.new("TextLabel"); TimeLabel.Size = UDim2.new(0, 50, 0, 20); TimeLabel.Position = UDim2.new(0.5, -25, 1, 2); TimeLabel.BackgroundTransparency = 1; TimeLabel.Text = tostring(pointDelay).."s"; TimeLabel.TextColor3 = Color3.fromRGB(85, 239, 196); TimeLabel.Font = Enum.Font.GothamBold; TimeLabel.TextSize = 12; TimeLabel.Parent = Dot | |
| local data = {id = id, frame = Dot, delay = pointDelay, timeLabel = TimeLabel, numLabel = NumLabel} | |
| table.insert(pointsData, data) | |
| local draggingPoint, dragStartPoint | |
| table.insert(connections, Dot.InputBegan:Connect(function(input) | |
| if isRunning or not Dot.Parent then return end | |
| if currentMode == "Move" and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then | |
| draggingPoint = true; dragStartPoint = input.Position | |
| elseif currentMode == "Time" and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then | |
| currentlyEditingPoint = data; TimeInput.Text = tostring(data.delay); TimePopup.Visible = true; LoadPopup.Visible = false; DataStorePopup.Visible = false | |
| elseif currentMode == "DeleteOne" and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then | |
| Dot:Destroy() | |
| for i, v in ipairs(pointsData) do | |
| if v == data then | |
| table.remove(pointsData, i) | |
| break | |
| end | |
| end | |
| refreshWaypointIndices() | |
| end | |
| end)) | |
| table.insert(connections, UserInputService.InputChanged:Connect(function(input) | |
| if draggingPoint and currentMode == "Move" and Dot.Parent and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then | |
| local delta = input.Position - dragStartPoint | |
| local newX = math.clamp(Dot.Position.X.Offset + delta.X, 20, workspace.CurrentCamera.ViewportSize.X - 20) | |
| local newY = math.clamp(Dot.Position.Y.Offset + delta.Y, 20, workspace.CurrentCamera.ViewportSize.Y - 20) | |
| Dot.Position = UDim2.new(0, newX, 0, newY) | |
| dragStartPoint = input.Position | |
| end | |
| end)) | |
| table.insert(connections, UserInputService.InputEnded:Connect(function(input) | |
| if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then | |
| draggingPoint = false | |
| end | |
| end)) | |
| end | |
| PopupSave.Activated:Connect(function() | |
| if currentlyEditingPoint and currentlyEditingPoint.frame and currentlyEditingPoint.frame.Parent then | |
| local newTime = tonumber(TimeInput.Text) | |
| if newTime and newTime >= 0.01 then | |
| currentlyEditingPoint.delay = newTime | |
| currentlyEditingPoint.timeLabel.Text = tostring(newTime) .. "s" | |
| end | |
| end | |
| TimePopup.Visible = false | |
| end) | |
| table.insert(connections, UserInputService.InputBegan:Connect(function(input) | |
| if currentMode == "Add" and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then | |
| if not isClickingOnMacroUI(input.Position) then createWaypoint(input.Position.X, input.Position.Y) end | |
| end | |
| end)) | |
| BtnAdd.Activated:Connect(function() setMode("Add") end) | |
| BtnMove.Activated:Connect(function() setMode("Move") end) | |
| BtnTime.Activated:Connect(function() setMode("Time") end) | |
| BtnDelOne.Activated:Connect(function() setMode("DeleteOne") end) | |
| -- SAVE SCRIPT | |
| BtnSave.Activated:Connect(function() | |
| if #pointsData == 0 then | |
| StatusLabel.Text = "Status: No points to save!" | |
| task.delay(2, function() if not isRunning then StatusLabel.Text = "Status: Resting" end end) | |
| return | |
| end | |
| local viewport = workspace.CurrentCamera.ViewportSize | |
| local exportTable = {} | |
| for _, data in ipairs(pointsData) do | |
| if data.frame and data.frame.Parent then | |
| local posX = data.frame.AbsolutePosition.X + (data.frame.AbsoluteSize.X / 2) | |
| local posY = data.frame.AbsolutePosition.Y + (data.frame.AbsoluteSize.Y / 2) | |
| table.insert(exportTable, {scaleX = posX / viewport.X, scaleY = posY / viewport.Y, delay = data.delay}) | |
| end | |
| end | |
| pcall(function() | |
| local jsonString = HttpService:JSONEncode(exportTable) | |
| JsonInbox.Text = jsonString | |
| end) | |
| StatusLabel.Text = "Status: Script saved to Inbox!" | |
| task.delay(3, function() if not isRunning then StatusLabel.Text = "Status: Resting" end end) | |
| end) | |
| -- LOAD SCRIPT | |
| BtnLoad.Activated:Connect(function() | |
| if isRunning then return end | |
| TimePopup.Visible = false | |
| DataStorePopup.Visible = false | |
| LoadPopup.Visible = not LoadPopup.Visible | |
| end) | |
| BtnDataStore.Activated:Connect(function() | |
| if isRunning then return end | |
| if not hasFileSupport then | |
| StatusLabel.Text = "Status: File system not supported!" | |
| return | |
| end | |
| TimePopup.Visible = false | |
| LoadPopup.Visible = false | |
| refreshSlotUI() | |
| DataStorePopup.Visible = not DataStorePopup.Visible | |
| end) | |
| DSCloseBtn.Activated:Connect(function() | |
| DataStorePopup.Visible = false | |
| end) | |
| PopupLoadBtn.Activated:Connect(function() | |
| local rawText = LoadInput.Text | |
| if rawText == "" then | |
| LoadPopup.Visible = false | |
| return | |
| end | |
| pcall(function() | |
| local decodedData = HttpService:JSONDecode(rawText) | |
| if type(decodedData) == "table" and #decodedData > 0 then | |
| for _, data in ipairs(pointsData) do | |
| if data.frame then data.frame:Destroy() end | |
| end | |
| safeClear(pointsData) | |
| setMode("None") | |
| local viewport = workspace.CurrentCamera.ViewportSize | |
| for _, item in ipairs(decodedData) do | |
| local px, py | |
| if item.scaleX and item.scaleY then | |
| px = item.scaleX * viewport.X | |
| py = item.scaleY * viewport.Y | |
| elseif item.x and item.y then | |
| px = item.x | |
| py = item.y | |
| end | |
| if px and py then | |
| createWaypoint(px, py, item.delay or 0.1) | |
| end | |
| end | |
| JsonInbox.Text = rawText | |
| StatusLabel.Text = "Status: Script loaded successfully!" | |
| else | |
| StatusLabel.Text = "Status: Invalid JSON format!" | |
| end | |
| end) | |
| LoadPopup.Visible = false | |
| task.delay(2.5, function() | |
| if not isRunning then StatusLabel.Text = "Status: Resting" end | |
| end) | |
| end) | |
| BtnClear.Activated:Connect(function() | |
| if isRunning then return end | |
| for _, data in ipairs(pointsData) do | |
| if data.frame then data.frame:Destroy() end | |
| end | |
| safeClear(pointsData) | |
| setMode("None") | |
| JsonInbox.Text = "" | |
| end) | |
| -- 5. RUN MACRO (HỖ TRỢ TUYỆT ĐỐI NATIVE PC MOUSE & MOBILE TOUCH) | |
| BtnStart.Activated:Connect(function() | |
| if #pointsData == 0 then return end | |
| if isRunning then | |
| isRunning = false | |
| if runThread then | |
| task.cancel(runThread) | |
| runThread = nil | |
| end | |
| BtnStart.Text = "▶️ START MACRO" | |
| BtnStart.BackgroundColor3 = Color3.fromRGB(0, 184, 148) | |
| setMode("None") | |
| return | |
| end | |
| isRunning = true | |
| currentMode = "Run" | |
| TimePopup.Visible = false | |
| LoadPopup.Visible = false | |
| DataStorePopup.Visible = false | |
| BtnStart.Text = "⏹️ STOP MACRO" | |
| BtnStart.BackgroundColor3 = Color3.fromRGB(214, 48, 49) | |
| runThread = task.spawn(function() | |
| while isRunning and ScreenGui and ScreenGui.Parent do | |
| for _, data in ipairs(pointsData) do | |
| if not isRunning or not ScreenGui or not ScreenGui.Parent then break end | |
| if data.frame and data.frame.Parent then | |
| pcall(function() | |
| data.frame.BackgroundColor3 = Color3.fromRGB(255, 71, 87) | |
| end) | |
| local clickX = data.frame.AbsolutePosition.X + (data.frame.AbsoluteSize.X / 2) | |
| local clickY = data.frame.AbsolutePosition.Y + (data.frame.AbsoluteSize.Y / 2) | |
| -- THỰC THI CLICK (Ưu tiên Native Mouse cho PC, fallback VirtualInputManager cho Mobile) | |
| pcall(function() | |
| if mousemoveabs and mouse1press and mouse1release then | |
| mousemoveabs(clickX, clickY) | |
| mouse1press() | |
| task.wait(0.05) | |
| mouse1release() | |
| else | |
| VirtualInputManager:SendMouseButtonEvent(clickX, clickY, 0, true, game, 1) | |
| task.wait(0.05) | |
| VirtualInputManager:SendMouseButtonEvent(clickX, clickY, 0, false, game, 1) | |
| end | |
| end) | |
| pcall(function() | |
| if not (mousemoveabs and mouse1press and mouse1release) then | |
| VirtualInputManager:SendTouchEvent(data.id, Enum.UserInputState.Begin, clickX, clickY) | |
| task.wait(0.05) | |
| VirtualInputManager:SendTouchEvent(data.id, Enum.UserInputState.End, clickX, clickY) | |
| end | |
| end) | |
| pcall(function() | |
| data.frame.BackgroundColor3 = Color3.fromRGB(255, 159, 67) | |
| end) | |
| local remainingTime = data.delay | |
| while remainingTime > 0 and isRunning and ScreenGui and ScreenGui.Parent do | |
| if not isMinimized then | |
| pcall(function() | |
| StatusLabel.Text = string.format("Button State: %d (%.1fs)", data.id, math.max(0, remainingTime)) | |
| end) | |
| end | |
| local step = math.min(0.1, remainingTime) | |
| task.wait(step) | |
| remainingTime = remainingTime - step | |
| end | |
| end | |
| end | |
| task.wait(0.01) | |
| end | |
| isRunning = false | |
| runThread = nil | |
| pcall(function() | |
| StatusLabel.Text = "Status: Resting" | |
| BtnStart.Text = "▶️ START MACRO" | |
| BtnStart.BackgroundColor3 = Color3.fromRGB(0, 184, 148) | |
| end) | |
| end) | |
| end) | |
| -- CLEANUP ON CLOSE | |
| CloseBtn.Activated:Connect(function() | |
| isRunning = false | |
| if runThread then | |
| task.cancel(runThread) | |
| runThread = nil | |
| end | |
| for _, conn in ipairs(connections) do | |
| if conn.Connected then conn:Disconnect() end | |
| end | |
| safeClear(connections) | |
| for _, data in ipairs(pointsData) do | |
| if data.frame then data.frame:Destroy() end | |
| end | |
| safeClear(pointsData) | |
| ScreenGui:Destroy() | |
| end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment