Auto paint
Key Required

Auto paint

Paint FlagsDark_FireDark_Fire 2.3K views 1.9K executesUpdated Jul 22, 2026
Unrated
00
Lua Script•625 lines (20981 chars)
--[[
    Paint Flags — Auto Paint
    Author: @Dark_Fire
    Version: 1.1

    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.1

    Можешь свободно использовать, изменять и распространять.
    Если будешь репостить — буду благодарен за упоминание, но это не обязательно.

    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
    gui.Destroying:Connect(function()
        local idx = table.find(guis, gui)
        if idx then table.remove(guis, idx) end
    end)
    
    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 ev = Instance.new("BindableEvent")
    ok.MouseButton1Click:Connect(function() ev:Fire() end)
    ev.Event:Wait()
    ev:Destroy()
    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 ev = Instance.new("BindableEvent")
    yes.MouseButton1Click:Connect(function() ev:Fire(true)  end)
    no.MouseButton1Click:Connect(function()  ev:Fire(false) end)
    local result = ev.Event:Wait()
    ev:Destroy()
    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 ev = Instance.new("BindableEvent")
    okBtn.MouseButton1Click:Connect(function() ev:Fire() end)
    ev.Event:Wait()
    ev:Destroy()
    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

local char = player.Character or player.CharacterAdded:Wait()
local hrp  = char:WaitForChild("HumanoidRootPart", 5)
if not hrp then
    stopMsg("Ошибка / Error",
        "Персонаж не найден. Сделай ресет и попробуй снова.\n\nCharacter not found. Reset and try again.",
        THEME.danger)
    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 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

hrp.Anchored = true

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
        hrp.Anchored   = false
        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
        hrp.Anchored   = false
        cam.CameraType = Enum.CameraType.Custom
        stopMsg("Покраска не проходит / Blocked", STALL_RU .. "\n\n" .. STALL_EN, THEME.danger)
        return
    end

    local ops = 0
    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)) * hrp.CFrame.Rotation
            ColorPixel:FireServer(cell.px)
            ops += 1
            if ops % 15 == 0 then task.wait() end
        end
    end

    task.wait(2)
end

hrp.Anchored   = false
cam.CameraType = Enum.CameraType.Custom
stopMsg("Не успел / Timed Out",
    "Не закрасило всё за отведённое время. Просто запусти скрипт ещё раз.\n\nCouldn't finish in time. Just run the script again.",
    THEME.warning)

Features & Information

- Fully automated: paints your flag without extra clicks - Top-down camera view to monitor painting - Built-in error checks (unclaimed canvas, server protections) - Simple UI with RU/EN guides
#auto paint#paint flags#paint#autofarm

Community Comments (1)

HenryzHenryzJul 23, 2026

Nice

More Scripts for Paint Flags