Component Type

Component

A Component represents a UI widget in the game interface. Components can be buttons, text labels, inventory slots, or any other UI element.

Methods

is_valid

component:is_valid() -> boolean

Checks if the component is still valid and exists.

Returns:

  • boolean: True if the component exists

Example:

local comp = components:get(149, 0)
if comp and comp:is_valid() then
    logger:info("Component is valid")
end

group_id

component:group_id() -> number

Returns the group ID (widget ID) of this component.

Returns:

  • number: The group ID

Example:

local comp = components:get(149, 0)
if comp then
    logger:info("Group ID: " .. comp:group_id())
end

component_id

component:component_id() -> number

Returns the component ID within the group.

Returns:

  • number: The component ID

Example:

local comp = components:get(149, 0)
if comp then
    logger:info("Component ID: " .. comp:component_id())
end

path

component:path() -> table

Returns the full path of IDs to this component.

Returns:

  • table: Array of IDs representing the path

Example:

local comp = components:get(149, 0)
if comp then
    local path = comp:path()
    local path_str = table.concat(path, " -> ")
    logger:info("Path: " .. path_str)
end

text

component:text() -> string

Returns the text content of this component.

Returns:

  • string: The component's text, or empty string if none

Example:

local comp = components:get(149, 0)
if comp then
    local text = comp:text()
    logger:info("Text: " .. text)
end

visible

component:visible() -> boolean

Checks if the component is visible.

Returns:

  • boolean: True if visible

Example:

local comp = components:get(149, 0)
if comp and comp:visible() then
    logger:info("Component is visible")
end

hidden

component:hidden() -> boolean

Checks if the component is hidden.

Returns:

  • boolean: True if hidden

Example:

local comp = components:get(149, 0)
if comp and comp:hidden() then
    logger:info("Component is hidden")
end

x

component:x() -> number

Returns the X position on screen.

Returns:

  • number: The X coordinate, or -1 if invalid

y

component:y() -> number

Returns the Y position on screen.

Returns:

  • number: The Y coordinate, or -1 if invalid

width

component:width() -> number

Returns the width in pixels.

Returns:

  • number: The width, or -1 if invalid

height

component:height() -> number

Returns the height in pixels.

Returns:

  • number: The height, or -1 if invalid

Example:

local comp = components:get(149, 0)
if comp then
    local x = comp:x()
    local y = comp:y()
    local w = comp:width()
    local h = comp:height()
    logger:info("Bounds: " .. x .. "," .. y .. " " .. w .. "x" .. h)
end

content_type

component:content_type() -> number

Returns the content type of this component.

Returns:

  • number: The content type ID, or -1 if invalid

Example:

local comp = components:get(149, 0)
if comp then
    logger:info("Content type: " .. comp:content_type())
end

parent_id

component:parent_id() -> number?

Returns the parent ID if this component has a parent.

Returns:

  • number?: The parent ID, or nil if no parent

Example:

local comp = components:get(149, 0)
if comp then
    local parent = comp:parent_id()
    if parent then
        logger:info("Parent ID: " .. parent)
    else
        logger:info("No parent")
    end
end

item_id

component:item_id() -> number

Returns the item ID if this component contains an item.

Returns:

  • number: The item ID, or -1 if no item

Example:

-- Check inventory slot
local slot = components:get(149, 0)
if slot then
    local item_id = slot:item_id()
    if item_id ~= -1 then
        logger:info("Contains item: " .. item_id)
    end
end

item_stack_size

component:item_stack_size() -> number

Returns the stack size if this component contains an item.

Returns:

  • number: The stack size, or -1 if no item

Example:

local slot = components:get(149, 0)
if slot then
    local stack = slot:item_stack_size()
    if stack > 1 then
        logger:info("Stack size: " .. stack)
    end
end

texture_id

component:texture_id() -> number

Returns the texture ID of this component. This can be used to identify components by their visual appearance.

Returns:

  • number: The texture ID, or -1 if invalid

Example:

local comp = components:get(149, 0)
if comp then
    local texture = comp:texture_id()
    if texture ~= -1 then
        logger:info("Component texture ID: " .. texture)
    end
end

click

component:click() -> boolean

Performs a left click on the component.

Returns:

  • boolean: True if successful

Example:

local button = components:get(149, 0)
if button and button:visible() then
    button:click()
end

interact

component:interact(filter_input: table?) -> boolean

Right-clicks and selects a menu option by filters.

Parameters:

  • filter_input (table, optional): Optional menu item filters

Returns:

  • boolean: True if successful

Example:

local item_slot = components:get(149, 5)
if item_slot then
    -- Right-click and select "Drop"
    item_slot:interact({action = "Drop"})
end

-- You can also use action_contains for substring matching
local button = components:get(149, 0)
if button then
    button:interact({action_contains = "Close"})
end

child

component:child(child_id: number) -> Component?

Gets a child component by its child ID. This is equivalent to calling components:get(group_id, component_id, child_id).

Parameters:

  • child_id (number): The child component ID to retrieve

Returns:

  • Component?: The child component, or nil if not found

Example:

-- Get parent component
local parent = components:get(465, 26)
if parent then
    -- Get child component 34
    local child = parent:child(34)
    if child then
        logger:info("Child text: " .. child:text())
    end
end

-- Equivalent to:
local child = components:get(465, 26, 34)

Note: The components:get() method accepts an optional third parameter for retrieving child components directly.


base_point

component:base_point() -> (number, number)

Returns the base point on screen (x, y) for this component.

Returns:

  • (number, number): Tuple of (x, y) screen coordinates, or (-1, -1) if invalid

next_point

component:next_point() -> (number, number)

Returns a random point within the component's clickable area on screen.

Returns:

  • (number, number): Tuple of (x, y) screen coordinates, or (-1, -1) if invalid

move_mouse_to

component:move_mouse_to() -> boolean

Move the mouse to this component with human-like movement.

Returns:

  • boolean: True on success, false if the position is invalid or the move fails

Example:

local comp = components:get(149, 0)
if comp and comp:move_mouse_to() then
    mouse:click()
end

track

component:track() -> boolean

Move the mouse to this component (one-shot; same as move_mouse_to()). Components do not support continuous tracking.

Returns:

  • boolean: True on success

Common Patterns

Checking Component Visibility

local function wait_for_component(group_id, component_id, timeout)
    local start = os.time()
    
    while os.time() - start < timeout do
        local comp = components:get(group_id, component_id)
        if comp and comp:is_valid() and comp:visible() then
            return comp
        end
        sleep(100)
    end
    
    return nil
end

local dialog = wait_for_component(231, 4, 5)
if dialog then
    logger:info("Dialog appeared!")
end

Reading Component Text

-- Read NPC dialog text
local function get_dialog_text()
    local dialog = components:get(231, 5)
    if dialog and dialog:visible() then
        return dialog:text()
    end
    return nil
end

local text = get_dialog_text()
if text then
    logger:info("NPC says: " .. text)
end

Clicking Buttons

local function click_continue_button()
    local continue_button = components:get(231, 4)
    
    if continue_button and continue_button:visible() then
        local x = continue_button:x()
        local y = continue_button:y()
        local w = continue_button:width()
        local h = continue_button:height()
        
        -- Click center of button
        mouse.move_to(x + w / 2, y + h / 2)
        sleep(100)
        mouse:click()
        return true
    end
    
    return false
end

Finding Item Slots

local function find_inventory_slot_with_item(item_id)
    -- Inventory slots are components 149:0 through 149:27
    for i = 0, 27 do
        local slot = components:get(149, i)
        if slot and slot:item_id() == item_id then
            return slot, i
        end
    end
    return nil, -1
end

local slot, index = find_inventory_slot_with_item(995)  -- Coins
if slot then
    logger:info("Found coins in slot " .. index)
end

Component Bounds Rectangle

local function get_component_bounds(comp)
    if not comp or not comp:is_valid() then
        return nil
    end
    
    return Rectangle.new(
        comp:x(),
        comp:y(),
        comp:width(),
        comp:height()
    )
end

local comp = components:get(149, 0)
if comp then
    local bounds = get_component_bounds(comp)
    if bounds then
        local area = bounds:area()
        logger:info("Component area: " .. area .. " pixels")
    end
end

Validating Component State

local function is_component_clickable(comp)
    if not comp then
        return false, "Component is nil"
    end
    
    if not comp:is_valid() then
        return false, "Component is not valid"
    end
    
    if comp:hidden() then
        return false, "Component is hidden"
    end
    
    if not comp:visible() then
        return false, "Component is not visible"
    end
    
    local w = comp:width()
    local h = comp:height()
    if w <= 0 or h <= 0 then
        return false, "Component has invalid dimensions"
    end
    
    return true, "Component is clickable"
end

local button = components:get(149, 0)
local clickable, reason = is_component_clickable(button)

if clickable then
    button:click()
else
    logger:warn("Cannot click: " .. reason)
end

Iterating Child Components

-- Find all visible children of a parent component
local function find_visible_children(parent_group_id, max_children)
    local visible = {}
    
    for i = 0, max_children do
        local child = components:get(parent_group_id, i)
        if child and child:is_valid() and child:visible() then
            table.insert(visible, child)
        end
    end
    
    return visible
end

local children = find_visible_children(149, 27)
logger:info("Found " .. #children .. " visible inventory slots")

Smart Component Clicking

local function smart_click_component(group_id, component_id)
    local comp = components:get(group_id, component_id)
    
    if not comp or not comp:is_valid() then
        logger:warn("Component not found")
        return false
    end
    
    if not comp:visible() then
        logger:warn("Component not visible")
        return false
    end
    
    -- Get center point
    local x = comp:x()
    local y = comp:y()
    local w = comp:width()
    local h = comp:height()
    
    -- Add small random offset for human-like clicking
    local offset_x = math.random(-w * 0.2, w * 0.2)
    local offset_y = math.random(-h * 0.2, h * 0.2)
    
    local click_x = x + w / 2 + offset_x
    local click_y = y + h / 2 + offset_y
    
    mouse.move_to(click_x, click_y)
    sleep(math.random(50, 150))
    mouse:click()
    
    return true
end

Monitoring Component Text Changes

local function wait_for_text_change(group_id, component_id, timeout)
    local comp = components:get(group_id, component_id)
    if not comp then return false end
    
    local initial_text = comp:text()
    local start = os.time()
    
    while os.time() - start < timeout do
        comp = components:get(group_id, component_id)
        if comp then
            local current_text = comp:text()
            if current_text ~= initial_text then
                return true, current_text
            end
        end
        sleep(100)
    end
    
    return false, initial_text
end

local changed, new_text = wait_for_text_change(231, 5, 10)
if changed then
    logger:info("Text changed to: " .. new_text)
end

Common Component IDs

Interface Components

-- Inventory
local INVENTORY_GROUP = 149

-- Bank
local BANK_GROUP = 12

-- Chatbox
local CHATBOX_GROUP = 162

-- Dialog
local DIALOG_GROUP = 231

-- Equipment
local EQUIPMENT_GROUP = 387

-- Spellbook
local SPELLBOOK_GROUP = 218

Using Component IDs

-- Check if inventory is open
local inventory_container = components:get(149, 0)
if inventory_container and inventory_container:visible() then
    logger:info("Inventory is open")
end

-- Check if bank is open
local bank_container = components:get(12, 2)
if bank_container and bank_container:visible() then
    logger:info("Bank is open")
end

See Also