--[[ Paint Flags — Auto Paint Author: @Dark_Fire Version: 1.0 Feel free to use, modify, and share it. If you repost it, I'd appreciate a mention — but no pressure either way. TG: @Dark_Firex --- Paint Flags — Авто-покраска Автор: @Dark_Fire Версия: 1.0 Можешь свободно использовать, изменять и распространять. Если будешь репостить — буду благодарен за упоминание, но это не обязательно. TG: @Dark_Firex ]] local STALL_LIMIT = 4 local RS = game:GetService("ReplicatedStorage") local player = game:GetService("Players").LocalPlayer local cam = workspace.CurrentCamera local DESC_RU = [[КАК ПОЛЬЗОВАТЬСЯ 1) Подойди к свободному холсту и нажми Claim Canvas. 2) В открывшемся меню выбери флаг и нажми Paint. 3) Дождись пока флаг появится на холсте и запусти скрипт. Скрипт автоматически закрасит весь флаг. Камера поднимется вверх, и ты увидишь как холст заполняется (или не увидишь лол). Когда всё готово — остановится сам. ⚠️ Скрипт красит очень быстро. Если покраска не идёт — возможно, сервер защищён от скриптов.]] local DESC_EN = [[HOW TO USE 1) Walk up to a free canvas and press Claim Canvas. 2) In the menu that opens, pick a flag and press Paint. 3) Wait for the flag to appear on the canvas, then run the script. The script automatically paints the entire flag. The camera will rise above the canvas so you can watch it fill in (or maybe you won't see it lol). When done, it stops on its own. ⚠️ The script paints very fast. If the painting is not going on, it is possible that the server is protected from scripts.]] local STALL_RU = "Покраска не проходит на сервер. Возможно, на сервере стоит защита от таких скриптов." local STALL_EN = "Paints aren't reaching the server. The server may have protection against scripts like this." local THEME = { scrim = Color3.fromRGB(0, 0, 0), card = Color3.fromRGB(20, 21, 25), field = Color3.fromRGB(14, 15, 18), stroke = Color3.fromRGB(46, 48, 56), strokeSoft = Color3.fromRGB(34, 35, 41), text = Color3.fromRGB(238, 239, 242), subtext = Color3.fromRGB(150, 153, 162), accent = Color3.fromRGB(80, 120, 248), onAccent = Color3.fromRGB(255, 255, 255), danger = Color3.fromRGB(216, 84, 84), warning = Color3.fromRGB(224, 164, 74), } local FONT = Enum.Font.Gotham local FONT_MED = Enum.Font.GothamMedium local FONT_BOLD = Enum.Font.GothamBold local function viewportSize() return (cam and cam.ViewportSize) or Vector2.new(1280, 720) end local function fitScale(baseW, baseH) local vp = viewportSize() local s = math.min((vp.X - 28) / baseW, (vp.Y - 28) / baseH) return math.clamp(s, 0.45, 1) end local function corner(inst, r) local c = Instance.new("UICorner") c.CornerRadius = UDim.new(0, r or 12) c.Parent = inst return c end local function stroke(inst, col, th) local s = Instance.new("UIStroke") s.Color = col or THEME.stroke s.Thickness = th or 1 s.ApplyStrokeMode = Enum.ApplyStrokeMode.Border s.Parent = inst return s end local function pad(inst, t, r, b, l) local p = Instance.new("UIPadding") p.PaddingTop = UDim.new(0, t) p.PaddingRight = UDim.new(0, r or t) p.PaddingBottom = UDim.new(0, b or t) p.PaddingLeft = UDim.new(0, l or r or t) p.Parent = inst return p end local function vstack(parent, gap) local l = Instance.new("UIListLayout") l.FillDirection = Enum.FillDirection.Vertical l.SortOrder = Enum.SortOrder.LayoutOrder l.Padding = UDim.new(0, gap or 12) l.Parent = parent return l end local function bindScale(card, sc, baseW, baseH) if not cam then return end local conn conn = cam:GetPropertyChangedSignal("ViewportSize"):Connect(function() if card and card.Parent then sc.Scale = fitScale(baseW, baseH) elseif conn then conn:Disconnect() end end) card.Destroying:Connect(function() if conn then conn:Disconnect() end end) end local guis = {} local function makeGui() local gui = Instance.new("ScreenGui") local nm = "" for _ = 1, math.random(8, 12) do nm = nm .. string.char(math.random(97, 122)) end gui.Name = nm gui.ResetOnSpawn = false gui.IgnoreGuiInset = true gui.DisplayOrder = 999999 gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling local ok = pcall(function() gui.Parent = (gethui and gethui()) or game:GetService("CoreGui") end) if not ok then gui.Parent = player:WaitForChild("PlayerGui") end guis[#guis+1] = gui return gui end local function scrim(gui) local f = Instance.new("Frame") f.Size = UDim2.fromScale(1, 1) f.BackgroundColor3 = THEME.scrim f.BackgroundTransparency = 0.38 f.BorderSizePixel = 0 f.Parent = gui return f end local function buildCard(parent, width, baseH) local card = Instance.new("Frame") card.AnchorPoint = Vector2.new(0.5, 0.5) card.Position = UDim2.fromScale(0.5, 0.5) card.Size = UDim2.fromOffset(width, 0) card.AutomaticSize = Enum.AutomaticSize.Y card.BackgroundColor3 = THEME.card card.BorderSizePixel = 0 card.Parent = parent corner(card, 14) stroke(card, THEME.stroke, 1) local sc = Instance.new("UIScale") sc.Scale = fitScale(width + 40, baseH or 320) sc.Parent = card bindScale(card, sc, width + 40, baseH or 320) return card end local function header(card, title, accentColor, order) local holder = Instance.new("Frame") holder.BackgroundTransparency = 1 holder.Size = UDim2.new(1, 0, 0, 0) holder.AutomaticSize = Enum.AutomaticSize.Y holder.LayoutOrder = order or 1 holder.Parent = card vstack(holder, 5) local tag = Instance.new("TextLabel") tag.BackgroundTransparency = 1 tag.Size = UDim2.new(1, 0, 0, 0) tag.AutomaticSize = Enum.AutomaticSize.Y tag.Font = FONT_BOLD tag.TextSize = 12 tag.Text = "AUTO-PAINT" tag.TextColor3 = accentColor or THEME.accent tag.TextXAlignment = Enum.TextXAlignment.Left tag.LayoutOrder = 1 tag.Parent = holder local ttl = Instance.new("TextLabel") ttl.BackgroundTransparency = 1 ttl.Size = UDim2.new(1, 0, 0, 0) ttl.AutomaticSize = Enum.AutomaticSize.Y ttl.Font = FONT_BOLD ttl.TextSize = 21 ttl.Text = title ttl.TextColor3 = THEME.text ttl.TextWrapped = true ttl.TextXAlignment = Enum.TextXAlignment.Left ttl.TextYAlignment = Enum.TextYAlignment.Top ttl.LayoutOrder = 2 ttl.Parent = holder return holder end local function divider(card, order) local d = Instance.new("Frame") d.Size = UDim2.new(1, 0, 0, 1) d.BackgroundColor3 = THEME.strokeSoft d.BorderSizePixel = 0 d.LayoutOrder = order or 2 d.Parent = card return d end local function bodyText(card, text, order) local l = Instance.new("TextLabel") l.BackgroundTransparency = 1 l.Size = UDim2.new(1, 0, 0, 0) l.AutomaticSize = Enum.AutomaticSize.Y l.Font = FONT l.TextSize = 15 l.Text = text l.TextColor3 = THEME.subtext l.TextWrapped = true l.TextXAlignment = Enum.TextXAlignment.Left l.TextYAlignment = Enum.TextYAlignment.Top l.LayoutOrder = order or 3 l.Parent = card return l end local function makeButton(parent, text, kind, order) local b = Instance.new("TextButton") b.AutoButtonColor = true b.Font = FONT_MED b.TextSize = 15 b.Text = text b.BorderSizePixel = 0 b.Size = UDim2.new(1, 0, 0, 46) b.LayoutOrder = order or 1 b.Parent = parent corner(b, 10) if kind == "primary" then b.BackgroundColor3 = THEME.accent b.TextColor3 = THEME.onAccent else b.BackgroundColor3 = THEME.field b.TextColor3 = THEME.text stroke(b, THEME.stroke, 1) end return b end local function buttonRow(card, order) local row = Instance.new("Frame") row.BackgroundTransparency = 1 row.Size = UDim2.new(1, 0, 0, 46) row.LayoutOrder = order or 4 row.Parent = card local h = Instance.new("UIListLayout") h.FillDirection = Enum.FillDirection.Horizontal h.HorizontalAlignment = Enum.HorizontalAlignment.Center h.VerticalAlignment = Enum.VerticalAlignment.Center h.SortOrder = Enum.SortOrder.LayoutOrder h.Padding = UDim.new(0, 10) h.Parent = row return row end local function showAlert(title, body, color) local gui = makeGui() scrim(gui) local card = buildCard(gui, 380, 300) pad(card, 20) vstack(card, 14) header(card, title, color, 1) divider(card, 2) bodyText(card, body, 3) local ok = makeButton(card, "OK", "primary", 4) local done = false ok.MouseButton1Click:Connect(function() done = true end) while not done do task.wait() end gui:Destroy() end local function askYesNo(title, body) local gui = makeGui() scrim(gui) local card = buildCard(gui, 380, 300) pad(card, 20) vstack(card, 14) header(card, title, THEME.accent, 1) divider(card, 2) bodyText(card, body, 3) local row = buttonRow(card, 4) local no = makeButton(row, "Нет / No", "secondary", 1) no.Size = UDim2.new(0.5, -5, 1, 0) local yes = makeButton(row, "Да / Yes", "primary", 2) yes.Size = UDim2.new(0.5, -5, 1, 0) local result = nil yes.MouseButton1Click:Connect(function() result = true end) no.MouseButton1Click:Connect(function() result = false end) while result == nil do task.wait() end gui:Destroy() return result end local function showInfo() local gui = makeGui() scrim(gui) local card = Instance.new("Frame") card.AnchorPoint = Vector2.new(0.5, 0.5) card.Position = UDim2.fromScale(0.5, 0.5) card.Size = UDim2.fromOffset(440, 560) card.BackgroundColor3 = THEME.card card.BorderSizePixel = 0 card.Parent = gui corner(card, 14) stroke(card, THEME.stroke, 1) local sc = Instance.new("UIScale") sc.Scale = fitScale(480, 600) sc.Parent = card bindScale(card, sc, 480, 600) pad(card, 20) local tag = Instance.new("TextLabel") tag.BackgroundTransparency = 1 tag.Position = UDim2.fromOffset(0, 0) tag.Size = UDim2.new(1, 0, 0, 16) tag.Font = FONT_BOLD tag.TextSize = 12 tag.Text = "AUTO-PAINT" tag.TextColor3 = THEME.accent tag.TextXAlignment = Enum.TextXAlignment.Left tag.Parent = card local title = Instance.new("TextLabel") title.BackgroundTransparency = 1 title.Position = UDim2.fromOffset(0, 22) title.Size = UDim2.new(1, 0, 0, 28) title.Font = FONT_BOLD title.TextSize = 21 title.Text = "Описание / Description" title.TextColor3 = THEME.text title.TextXAlignment = Enum.TextXAlignment.Left title.Parent = card local seg = Instance.new("Frame") seg.Position = UDim2.fromOffset(0, 60) seg.Size = UDim2.new(1, 0, 0, 40) seg.BackgroundColor3 = THEME.field seg.BorderSizePixel = 0 seg.Parent = card corner(seg, 10) stroke(seg, THEME.strokeSoft, 1) pad(seg, 4) local ruBtn = Instance.new("TextButton") ruBtn.AnchorPoint = Vector2.new(0, 0.5) ruBtn.Position = UDim2.new(0, 0, 0.5, 0) ruBtn.Size = UDim2.new(0.5, -3, 1, 0) ruBtn.AutoButtonColor = false ruBtn.Font = FONT_MED ruBtn.TextSize = 14 ruBtn.Text = "Русский" ruBtn.BorderSizePixel = 0 ruBtn.Parent = seg corner(ruBtn, 8) local enBtn = Instance.new("TextButton") enBtn.AnchorPoint = Vector2.new(1, 0.5) enBtn.Position = UDim2.new(1, 0, 0.5, 0) enBtn.Size = UDim2.new(0.5, -3, 1, 0) enBtn.AutoButtonColor = false enBtn.Font = FONT_MED enBtn.TextSize = 14 enBtn.Text = "English" enBtn.BorderSizePixel = 0 enBtn.Parent = seg corner(enBtn, 8) local scroll = Instance.new("ScrollingFrame") scroll.Position = UDim2.fromOffset(0, 112) scroll.Size = UDim2.new(1, 0, 1, -(112 + 58)) scroll.BackgroundColor3 = THEME.field scroll.BorderSizePixel = 0 scroll.ScrollBarThickness = 5 scroll.ScrollBarImageColor3 = THEME.subtext scroll.ScrollBarImageTransparency = 0.25 scroll.ScrollingDirection = Enum.ScrollingDirection.Y scroll.CanvasSize = UDim2.new(0, 0, 0, 0) scroll.AutomaticCanvasSize = Enum.AutomaticSize.Y scroll.Parent = card corner(scroll, 10) stroke(scroll, THEME.strokeSoft, 1) pad(scroll, 14) local body = Instance.new("TextLabel") body.BackgroundTransparency = 1 body.Size = UDim2.new(1, 0, 0, 0) body.AutomaticSize = Enum.AutomaticSize.Y body.Font = FONT body.TextSize = 15 body.Text = DESC_RU body.TextColor3 = THEME.text body.TextWrapped = true body.TextXAlignment = Enum.TextXAlignment.Left body.TextYAlignment = Enum.TextYAlignment.Top body.Parent = scroll local function setLang(lang) if lang == "ru" then body.Text = DESC_RU ruBtn.BackgroundColor3 = THEME.accent; ruBtn.TextColor3 = THEME.onAccent enBtn.BackgroundColor3 = THEME.field; enBtn.TextColor3 = THEME.subtext else body.Text = DESC_EN enBtn.BackgroundColor3 = THEME.accent; enBtn.TextColor3 = THEME.onAccent ruBtn.BackgroundColor3 = THEME.field; ruBtn.TextColor3 = THEME.subtext end end setLang("ru") ruBtn.MouseButton1Click:Connect(function() setLang("ru") end) enBtn.MouseButton1Click:Connect(function() setLang("en") end) local okBtn = Instance.new("TextButton") okBtn.AnchorPoint = Vector2.new(0.5, 1) okBtn.Position = UDim2.new(0.5, 0, 1, 0) okBtn.Size = UDim2.new(1, 0, 0, 46) okBtn.AutoButtonColor = true okBtn.Font = FONT_MED okBtn.TextSize = 15 okBtn.Text = "Понятно / Got it" okBtn.BackgroundColor3 = THEME.accent okBtn.TextColor3 = THEME.onAccent okBtn.BorderSizePixel = 0 okBtn.Parent = card corner(okBtn, 10) local done = false okBtn.MouseButton1Click:Connect(function() done = true end) while not done do task.wait() end gui:Destroy() end local function killAll() for _, g in ipairs(guis) do pcall(function() g:Destroy() end) end table.clear(guis) end local function stopMsg(title, body, color) showAlert(title, body, color) killAll() end local wantInfo = askYesNo("Авто-покраска", "Показать короткую инструкцию?\nShow a short how-to?") if wantInfo then showInfo() end local run = askYesNo("Запуск / Run", "Запустить покраску сейчас?\nStart painting now?") if not run then return end local claimedBase = nil local bases = workspace:FindFirstChild("Bases") if bases then for _, b in pairs(bases:GetChildren()) do if b:IsA("BasePart") and b:GetAttribute("Owner") == player.UserId then claimedBase = b break end end end if not claimedBase then showAlert("Холст не занят / Canvas Not Claimed", "Подойди к свободному холсту и нажми Claim Canvas, потом запусти скрипт снова.\n\nWalk up to a free canvas and press Claim Canvas, then run the script again.", THEME.warning) return end local folder = workspace:FindFirstChild(tostring(player.UserId)) local canvasBase = folder and folder:FindFirstChild("CanvasBase") if not canvasBase then showAlert("Флаг не выбран / No Flag Selected", "Холст занят, но флаг ещё не выбран. Выбери флаг в меню → нажми Paint → дождись загрузки → запусти скрипт.\n\nCanvas is claimed but no flag selected. Pick a flag → press Paint → wait for it to load → run the script.", THEME.warning) return end local ColorPixel = RS.RemoteEvents.ColorPixel local SetCurrentColor = RS.RemoteEvents.SetCurrentColor local GetPixelInfo = RS.RemoteFunctions.GetPixelInfo local CheckIfPainted = RS.RemoteFunctions.CheckIfPainted local W = canvasBase.Size.X * 2 local H = canvasBase.Size.Z * 2 local RADIUS = player:GetAttribute("BrushRadius") or 8 local STEP = math.floor(RADIUS * 1.8) local pixelMap = GetPixelInfo:InvokeServer() if not pixelMap then showAlert("Флаг не выбран / No Flag Selected", "Холст занят, но флаг ещё не выбран. Выбери флаг в меню → нажми Paint → дождись загрузки → запусти скрипт.\n\nCanvas is claimed but no flag selected. Pick a flag → press Paint → wait for it to load → run the script.", THEME.warning) return end local hasPixels = false for _, rows in pairs(pixelMap) do for _, ci in pairs(rows) do if ci ~= 0 then hasPixels = true break end end if hasPixels then break end end if not hasPixels then showAlert("Флаг не выбран / No Flag Selected", "Холст занят, но флаг ещё не выбран. Выбери флаг в меню → нажми Paint → дождись загрузки → запусти скрипт.\n\nCanvas is claimed but no flag selected. Pick a flag → press Paint → wait for it to load → run the script.", THEME.warning) return end cam.CameraType = Enum.CameraType.Scriptable cam.CFrame = CFrame.new( canvasBase.Position + Vector3.new(0, math.max(canvasBase.Size.X, canvasBase.Size.Z) * 1.2, 0), canvasBase.Position ) local hrp = (player.Character or player.CharacterAdded:Wait()):WaitForChild("HumanoidRootPart") local function c2w(col, row) local lx = (col - 0.5) / W * canvasBase.Size.X - canvasBase.Size.X / 2 local lz = canvasBase.Size.Z / 2 - (row - 0.5) / H * canvasBase.Size.Z return canvasBase.CFrame:PointToWorldSpace(Vector3.new(lx, 3, lz)) end local lastRem = math.huge local stalls = 0 for round = 1, 10 do local pm = CheckIfPainted:InvokeServer() or {} local plan = {} local rem = 0 for col, rows in pairs(pixelMap) do for row, ci in pairs(rows) do if ci ~= 0 and not (pm[col] and pm[col][row] == true) then rem += 1 local gc = math.ceil(col / STEP) local gr = math.ceil(row / STEP) local ac = math.clamp((gc-1)*STEP + math.ceil(STEP/2), 1, W) local ar = math.clamp((gr-1)*STEP + math.ceil(STEP/2), 1, H) local key = gc * 100000 + gr if not plan[ci] then plan[ci] = {} end if not plan[ci][key] then plan[ci][key] = {ac=ac, ar=ar, px={}} end local t = plan[ci][key].px t[#t+1] = {col, row} end end end if rem == 0 then cam.CameraType = Enum.CameraType.Custom killAll() return end if rem >= lastRem then stalls += 1 else stalls = 0 end lastRem = rem if stalls >= STALL_LIMIT then cam.CameraType = Enum.CameraType.Custom stopMsg("Покраска не проходит / Blocked", STALL_RU .. "\n\n" .. STALL_EN, THEME.danger) return end for ci, cells in pairs(plan) do SetCurrentColor:FireServer(ci) for _, cell in pairs(cells) do hrp.CFrame = CFrame.new(c2w(cell.ac, cell.ar)) ColorPixel:FireServer(cell.px) end end task.wait(2) end cam.CameraType = Enum.CameraType.Custom stopMsg("Не успел / Timed Out", "Не закрасило всё за отведённое время. Просто запусти скрипт ещё раз.\n\nCouldn't finish in time. Just run the script again.", THEME.warning)