Paint

Category: Development

Paint System

The Paint system allows scripts to create custom overlay windows that display runtime information, statistics, and progress tracking. These overlays appear on top of the game window and provide real-time feedback to users about script execution.

What is Paint?

Paint overlays are draggable, customizable windows that can display:

  • Static text (script name, version)
  • Dynamic text (current status, player health)
  • Skill XP tracking (automatic XP gained and XP/hour)
  • Item tracking (automatic item quantity changes)
  • Counters (custom counters you update programmatically)
  • Progress bars (visual progress indicators)

Basic Concepts

Builder Pattern

The Paint API uses a builder pattern, which allows you to chain method calls to configure your paint:

local paint_id = paint:new_builder()
    :with_position(10, 10)
    :with_size(300, 200)
    :add_string("My Script v1.0")
    :track_skill("Mining")
    :build()

Paint Lifecycle

  1. Create: Use paint:new_builder() to start building
  2. Configure: Chain methods to set position, size, colors, and content
  3. Build: Call build() to create and register the paint (returns paint ID)
  4. Update: Use paint management functions to update content during execution
  5. Remove: Call paint:remove() when done

Common Use Cases

Displaying Script Status

Show users what the script is currently doing:

local paint_id = paint:new_builder()
    :with_position(10, 10)
    :add_string("Status", function()
        if inventory:full() then
            return "Banking..."
        else
            return "Mining..."
        end
    end)
    :build()

Tracking Progress

Display skill XP and item gains:

local paint_id = paint:new_builder()
    :track_skill("Mining")  -- Shows: "Mining: +123 XP (456 XP/hr)"
    :track_item({name = "Iron ore"}, "Iron ore", true)  -- Shows: "Iron ore: +5 (120/hr)"
    :build()

Visual Feedback

Use progress bars to show completion status:

local paint_id = paint:new_builder()
    :add_progress_bar("Inventory", 0, 28)
    :build()

-- Update during execution
function update_inventory_display()
    local count = inventory:count()
    paint:update_progress_bar(paint_id, "Inventory", count, 28)
end

Best Practices

Performance

  • Don't update too frequently: Update paints every 1-2 seconds, not every tick
  • Use dynamic functions: For frequently changing values, use functions in add_string() rather than manually updating
-- Good: Function is called automatically
builder:add_string("HP", function()
    return combat:current_health() .. "/" .. combat:max_health()
end)

-- Less efficient: Requires manual updates
builder:add_string("HP", "0/0")
-- Then manually: paint:update_rows(...)

Organization

  • Group related information: Use multiple paints for different purposes (status, stats, debug)
  • Consistent styling: Use the same colors and sizes across your paints
  • Clear labels: Make sure all paint elements have descriptive labels

User Experience

  • Default positions: Set sensible default positions that don't obstruct gameplay
  • Allow customization: Don't disable dragging unless necessary
  • Provide context: Include script name and version in your paint

Example: Complete Mining Script Paint

local function create_mining_paint()
    local builder = paint:new_builder()
    
    -- Position and appearance
    builder:with_position(10, 10)
    builder:with_size(350, 300)
    builder:with_anchor("top_left")
    builder:with_text_size(13.0)
    builder:with_background_color(15, 15, 15, 220)
    builder:with_text_color(220, 220, 220, 255)
    
    -- Header
    builder:add_string("Mining Script v2.1")
    builder:add_string("")  -- Blank line
    
    -- Automatic tracking
    builder:track_skill("Mining")
    builder:track_item({name = "Iron ore"}, "Iron ore", true)
    builder:track_item({name = "Coal"}, "Coal", true)
    
    -- Custom counters
    builder:add_counter("Trips Completed", 0)
    builder:add_counter("Ores Mined", 0)
    
    -- Progress bar
    builder:add_progress_bar("Inventory", 0, 28)
    
    -- Dynamic status
    builder:add_string("Status", function()
        if inventory:full() then
            return "Banking..."
        elseif movement:is_moving() then
            return "Walking..."
        else
            return "Mining..."
        end
    end)
    
    return builder:build()
end

-- In your script
local paint_id = create_mining_paint()

function script:poll()
    -- Update counters
    paint:update_counter(paint_id, "Trips Completed", trip_count)
    paint:update_counter(paint_id, "Ores Mined", ore_count)
    
    -- Update progress bar
    local inv_count = inventory:count()
    paint:update_progress_bar(paint_id, "Inventory", inv_count, 28)
    
    -- Your script logic...
    sleep(50)
end

Next Steps