Loadout API

Category: API Reference

Declarative system for managing inventory and equipment configurations with automatic item acquisition from bank and Grand Exchange.

Overview

The Loadout API provides a high-level way to:

  • Define desired inventory and equipment setups
  • Automatically acquire items from bank or Grand Exchange
  • Check compliance with loadout requirements
  • Handle strict mode (deposit extra items) or permissive mode (allow extras)
  • Configure Grand Exchange purchasing with price limits and timeouts
  • Control item acquisition sources (bank only, GE only, auto)
  • Specify restock amounts and noted item preferences

Migration Guide

If you're updating from the old API, here are the key changes:

Old API:

inv:item(filter, 10)
inv:item_noted(filter, 100)
inv:item_range(filter, 10, 20)
inv:item_noted_range(filter, 50, 100)
inv:item_fill(filter, 5)

New API:

inv:item(filter, {amount = 10})
inv:item(filter, {amount = 100, noted = true})
inv:item_range(filter, {min = 10, max = 20})
inv:item_range(filter, {min = 50, max = 100, noted = true})
inv:item_fill(filter, {except_slot_count = 5})

Benefits:

  • Removed duplicate _noted functions - use noted = true in config instead
  • Added restock_amount to control withdrawal amounts
  • Added source control to specify where items come from
  • More extensible - new features can be added without new functions

Constants

ItemSource

Enum for controlling where items can be acquired from:

loadout.ItemSource.AUTO         -- Try bank first, then GE if enabled
loadout.ItemSource.BANK_ONLY    -- Only acquire from bank
loadout.ItemSource.GE_ONLY      -- Only acquire from GE
loadout.ItemSource.NO_ACQUIRE   -- Don't acquire, must already have

Functions

builder

loadout:builder() -> LoadoutBuilder

Create a new loadout builder.

Returns:

  • LoadoutBuilder - Builder for constructing loadout

Example:

local builder = loadout:builder()

apply

loadout:apply(definition: LoadoutDefinition) -> table

Apply a loadout definition. This will:

  1. Check current compliance
  2. Deposit extra items if strict mode enabled
  3. Withdraw missing items from bank
  4. Buy missing items from GE if enabled
  5. Equip equipment items
  6. Retry until compliant or max attempts reached

Parameters:

ParameterTypeRequiredDescription
definitionLoadoutDefinitionYesLoadout to apply

Returns:

  • table - Result with fields:
    • success (boolean) - Whether loadout was applied successfully
    • attempts (number) - Number of attempts made
    • reason (string, optional) - Error reason if failed
    • partial (boolean, optional) - True if partially applied
    • missing_items (table, optional) - Items that couldn't be acquired

Example:

local def = loadout:builder()
    :settings(function(s)
        s.strict_mode = false
        s.ge_enabled = true
        s.max_ge_cost_per_item = 10000
        s.max_ge_cost_total = 50000
        s.ge_price_multiplier = 1.5
        s.ge_offer_wait_time_minutes = 2
        s.max_attempts = 3
    end)
    :inventory(function(inv)
        inv:item({id = 995}, {amount = 10000})
        inv:item_fill({name = "Bronze bar"}, {except_slot_count = 0})
        inv:item({name = "Death rune"}, {amount = 1})
        inv:item({name = "Raw shrimps"}, {amount =2})
    end)
    :equipment(function(equip)
    equip:item({name_contains = "Bronze pickaxe"}, {amount=1})
    end)
    :build()

local result = loadout:apply(def)
if result.success then
    logger:info("Loadout applied in " .. result.attempts .. " attempts")
else
    logger:error("Failed: " .. result.reason)
end

check

loadout:check(definition: LoadoutDefinition) -> table

Check if current inventory/equipment matches loadout requirements without making changes.

Parameters:

ParameterTypeRequiredDescription
definitionLoadoutDefinitionYesLoadout to check against

Returns:

  • table - Compliance result with fields:
    • compliant (boolean) - True if loadout requirements are met
    • missing_items (table) - Array of missing item info
    • extra_items (table) - Array of extra item IDs (in strict mode)

Example:

local compliance = loadout:check(def)

if compliance.compliant then
    logger:info("Loadout is compliant!")
else
    for _, missing in ipairs(compliance.missing_items) do
        logger:warn("Missing: " .. missing.item_name .. 
            " (need " .. missing.required .. ", have " .. missing.available .. ")")
    end
end

LoadoutBuilder Methods

inventory

builder:inventory(callback: function) -> LoadoutBuilder

Configure inventory items using a callback function.

Parameters:

ParameterTypeRequiredDescription
callbackfunctionYesFunction receiving InventoryLoadoutBuilder

Returns:

  • LoadoutBuilder - Self for chaining

Example:

builder:inventory(function(inv)
    inv:item({id = 995}, {amount = 10000})     -- 10k coins by ID
    inv:item({name = "Lobster"}, {amount = 5}) -- 5 lobsters by name
end)

equipment

builder:equipment(callback: function) -> LoadoutBuilder

Configure equipment items using a callback function.

Parameters:

ParameterTypeRequiredDescription
callbackfunctionYesFunction receiving EquipmentLoadoutBuilder

Returns:

  • LoadoutBuilder - Self for chaining

Example:

builder:equipment(function(eq)
    eq:item({id = 4151}, {amount = 1})              -- Abyssal whip by ID
    eq:item({name = "Rune platebody"}, {amount = 1}) -- By name
end)

settings

builder:settings(callback: function) -> LoadoutBuilder

Configure loadout behavior using a callback function.

Parameters:

ParameterTypeRequiredDescription
callbackfunctionYesFunction receiving settings table to modify

Returns:

  • LoadoutBuilder - Self for chaining

Settings Table Fields:

FieldTypeDefaultDescription
strict_modebooleanfalseDeposit extra equipment items not in loadout
ge_enabledbooleanfalseAllow Grand Exchange purchases
max_ge_cost_per_itemnumbernilMax cost per item from GE
max_ge_cost_totalnumbernilMax total GE spending
ge_price_multipliernumber1.5Price multiplier for GE offers
ge_offer_wait_time_minutesnumber5How long to wait for GE offers
max_attemptsnumber5Max retry attempts

Example:

builder:settings(function(s)
    s.strict_mode = true
    s.ge_enabled = true
    s.max_ge_cost_per_item = 10000
    s.max_ge_cost_total = 50000
    s.ge_price_multiplier = 1.5
    s.ge_offer_wait_time_minutes = 2
    s.max_attempts = 3
end)

build

builder:build() -> LoadoutDefinition

Build the final loadout definition.

Returns:

  • LoadoutDefinition - Immutable loadout configuration

Example:

local def = builder:build()

InventoryLoadoutBuilder Methods

item

inv:item(filter: table, config: table)

Add an item with exact quantity using an item filter and configuration.

Parameters:

ParameterTypeRequiredDescription
filtertableYesItem filter (see Filter Options below)
configtableYesConfiguration with fields:
  • noted (boolean, optional) - Whether item should be noted (default: false)
  • restock_amount (number, optional) - Override amount to withdraw/buy when restocking
  • source (string, optional) - Item source from loadout.ItemSource enum

Examples:

-- Basic usage
inv:item({id = 995}, {amount = 10000})  -- 10k coins

-- Noted items
inv:item({name = "Bronze bar"}, {amount = 100, noted = true})

-- With restock amount (withdraw 200 but only require 100)
inv:item({name = "Lobster"}, {amount = 100, restock_amount = 200})

-- From bank only
inv:item({name = "Dragon scimitar"}, {
    amount = 1,
    source = loadout.ItemSource.BANK_ONLY
})

-- Complex configuration
inv:item({name_contains = "potion"}, {
    amount = 5,
    noted = true,
    restock_amount = 10,
    source = loadout.ItemSource.AUTO
})

item_range

inv:item_range(filter: table, config: table)

Add an item with a quantity range.

Parameters:

ParameterTypeRequiredDescription
filtertableYesItem filter
configtableYesConfiguration with fields:
  • max (number, required) - Maximum quantity allowed
  • noted (boolean, optional) - Whether item should be noted
  • restock_amount (number, optional) - Override amount to withdraw/buy
  • source (string, optional) - Item source from loadout.ItemSource enum

Examples:

-- Basic range
inv:item_range({name = "Shark"}, {min = 10, max = 20})

-- Noted range
inv:item_range({name = "Coal"}, {min = 50, max = 100, noted = true})

-- With source control
inv:item_range({name = "Dragon bones"}, {
    min = 100,
    max = 500,
    noted = true,
    source = loadout.ItemSource.BANK_ONLY
})

item_fill

inv:item_fill(filter: table, config: table)

Add an item that fills remaining inventory slots.

Parameters:

ParameterTypeRequiredDescription
filtertableYesItem filter
configtableYesConfiguration with fields:
  • restock_amount (number, optional) - Override amount to withdraw/buy
  • source (string, optional) - Item source from loadout.ItemSource enum

Examples:

-- Fill all remaining slots
inv:item_fill({id = 1511}, {})

-- Leave some slots free
inv:item_fill({name = "Lobster"}, {except_slot_count = 5})

-- Fill from bank only
inv:item_fill({name_any = {"Shark", "Monkfish"}}, {
    except_slot_count = 3,
    source = loadout.ItemSource.BANK_ONLY
})

ignore_item

inv:ignore_item(filter: table, config?: table)

Add an item to ignore for compliance checking. Ignored items won't cause compliance failures, but their behavior in extra_items can be controlled.

Parameters:

ParameterTypeRequiredDescription
filtertableYesItem filter matching items to ignore
configtable, optionalNoConfiguration with fields:

Use Cases:

  • Items that your script collects during activities (ores, logs, etc.)
  • Items that may be picked up but aren't part of the loadout
  • Items you want to allow but don't want to enforce

Examples:

-- Ignore a specific item (default: deposit=true, included in extra_items)
inv:ignore_item({name = "Coal"})

-- Ignore items by name pattern
inv:ignore_item({name_contains = "ore"})

-- Ignore but don't deposit (fully ignored, not in extra_items)
inv:ignore_item({name = "Uncut gem"}, {deposit = false})

-- Ignore and allow deposit in strict mode (default behavior)
inv:ignore_item({name = "Coal"}, {deposit = true})

-- Ignore multiple specific items
inv:ignore_item({name_any = {"Coal", "Iron ore", "Mithril ore"}})

-- Ignore by ID
inv:ignore_item({id = 453})

-- Ignore multiple IDs
inv:ignore_item({ids = {453, 440, 442}})  -- Coal, Iron ore, Silver ore

Note:

  • If deposit = true (default): Ignored items are included in the extra_items list and can be deposited in strict mode, but they don't cause compliance failures.
  • If deposit = false: Ignored items are fully ignored and not included in extra_items at all.

EquipmentLoadoutBuilder Methods

item

eq:item(filter: table, config: table)

Add an equipment item using an item filter and configuration.

Parameters:

ParameterTypeRequiredDescription
filtertableYesItem filter (see Filter Options below)
configtableYesConfiguration with fields:
  • restock_amount (number, optional) - Override withdrawal/buy amount
  • source (string, optional) - Item source from loadout.ItemSource

Example:

eq:item({id = 4151}, {amount = 1})  -- Abyssal whip
eq:item({name = "Dragon boots"}, {
    amount = 1,
    restock_amount = 2,
    source = loadout.ItemSource.BANK_ONLY
})

ignore_item

eq:ignore_item(filter: table, config?: table)

Add an equipment item to ignore for compliance checking. Ignored items won't cause compliance failures, but their behavior in extra_items can be controlled.

Parameters:

ParameterTypeRequiredDescription
filtertableYesItem filter matching equipment items to ignore
configtable, optionalNoConfiguration with fields:

Use Cases:

  • Equipment items that may be collected or swapped during activities
  • Alternative equipment that's acceptable but not required
  • Items you want to allow but don't want to enforce

Examples:

-- Ignore a specific equipment item (default: deposit=true)
eq:ignore_item({name = "Bronze axe"})

-- Ignore items by name pattern
eq:ignore_item({name_contains = "pickaxe"})

-- Ignore but don't deposit (fully ignored, not in extra_items)
eq:ignore_item({name = "Bronze axe"}, {deposit = false})

-- Ignore multiple items
eq:ignore_item({name_any = {"Bronze axe", "Iron axe", "Steel axe"}})

-- Ignore by ID
eq:ignore_item({id = 1351})  -- Iron axe

Note:

  • If deposit = true (default): Ignored items are included in the extra_items list and can be deposited in strict mode, but they don't cause compliance failures.
  • If deposit = false: Ignored items are fully ignored and not included in extra_items at all.

Filter Options

Item filters use the same format as inventory/bank filters:

FilterTypeDescription
idnumberExact item ID
idstableArray of item IDs to match
namestringExact name match
name_containsstringName contains text
name_anytableMatch if name equals any in array
name_contains_anytableMatch if name contains any substring

Examples:

{id = 995}                          -- Coins by ID
{name = "Abyssal whip"}             -- By exact name
{name_contains = "potion"}          -- Any potion
{ids = {385, 7946, 379}}            -- Shark, Monkfish, or Lobster
{name_any = {"Shark", "Lobster"}}  -- Either shark or lobster

Complete Examples

Basic Combat Loadout

local combat_def = loadout:builder()
    :inventory(function(inv)
        inv:item({name = "Shark"}, {amount = 10})
        inv:item({name_contains = "Prayer potion"}, {amount = 2})
    end)
    :equipment(function(eq)
        eq:item({name = "Abyssal whip"}, {amount = 1})
        eq:item({name = "Dragon defender"}, {amount = 1})
        eq:item({name = "Fighter torso"}, {amount = 1})
    end)
    :settings(function(s)
        s.strict_mode = true
        s.max_attempts = 3
    end)
    :build()

local result = loadout:apply(combat_def)
if result.success then
    logger:info("Ready for combat!")
end

Skilling with GE Fallback

local mining_def = loadout:builder()
    :inventory(function(inv)
        inv:item({name_contains = "pickaxe"}, {amount = 1})
    end)
    :settings(function(s)
        s.ge_enabled = true
        s.max_ge_cost_total = 50000
        s.ge_price_multiplier = 1.5
    end)
    :build()

local result = loadout:apply(mining_def)
if result.success then
    logger:info("Ready to mine!")
elseif result.partial then
    logger:warn("Some items missing: " .. result.reason)
else
    logger:error("Can't start: " .. result.reason)
end

Flexible Food Selection

local food_def = loadout:builder()
    :inventory(function(inv)
        -- Accept any high-tier food, fill inventory except 5 slots
        inv:item_fill({name_any = {"Shark", "Monkfish", "Lobster"}}, {
            except_slot_count = 5
        })
    end)
    :build()

loadout:apply(food_def)

Skilling with Noted Items

local smithing_def = loadout:builder()
    :inventory(function(inv)
        inv:item({name = "Hammer"}, {amount = 1})
        inv:item({name = "Bronze bar"}, {amount = 100, noted = true})
        inv:item_range({name = "Coal"}, {min = 50, max = 100, noted = true})
    end)
    :settings(function(s)
        s.strict_mode = true
        s.ge_enabled = true
        s.max_ge_cost_total = 100000
    end)
    :build()

local result = loadout:apply(smithing_def)
if result.success then
    logger:info("Ready to smith!")
end

Mining with Ignore Items

local mining_def = loadout:builder()
    :inventory(function(inv)
        inv:item({name_contains = "pickaxe"}, {amount = 1})
        -- Ignore ores that may be collected during mining
        inv:ignore_item({name_contains = "ore"})
        inv:ignore_item({name = "Coal"})
        inv:ignore_item({name = "Uncut gem"})
    end)
    :equipment(function(eq)
        eq:item({name_contains = "pickaxe"}, {amount = 1})
        -- Ignore alternative pickaxes that might be collected
        eq:ignore_item({name_any = {"Bronze pickaxe", "Iron pickaxe"}})
    end)
    :settings(function(s)
        s.strict_mode = false  -- Allow extra items (ores)
        s.max_attempts = 3
    end)
    :build()

local result = loadout:apply(mining_def)
if result.success then
    logger:info("Ready to mine! Ores collected will be ignored for compliance.")
end

This example shows how ignore items work:

  • The loadout requires a pickaxe in inventory and equipment
  • Any ores, coal, or gems collected during mining won't cause compliance failures
  • The loadout will still be considered compliant even if you have extra ores
  • In strict mode, ignored items can still be deposited if needed

Compliance Check Only

local required = loadout:builder()
    :inventory(function(inv)
        inv:item({id = 995}, {amount = 10000})  -- Need 10k coins
    end)
    :build()

-- Just check, don't modify
local compliance = loadout:check(required)

if not compliance.compliant then
    logger:warn("Not ready - missing items!")
    for _, missing in ipairs(compliance.missing_items) do
        local needed = missing.required - missing.available
        logger:warn("Need " .. needed .. " more " .. missing.item_name)
    end
end

Banking Loop with Loadout

local trip_loadout = loadout:builder()
    :inventory(function(inv)
        inv:item({name = "Lobster"}, {amount = 20})
    end)
    :equipment(function(eq)
        eq:item({name = "Bronze axe"}, {amount = 1})
    end)
    :build()

while true do
    -- Apply loadout (handles banking automatically)
    local result = loadout:apply(trip_loadout)
    
    if not result.success then
        logger:error("Can't continue: " .. result.reason)
        break
    end
    
    -- Do activity
    perform_task()
    
    -- Loop back to reapply loadout
end

Advanced: Item Source Control

local advanced_def = loadout:builder()
    :inventory(function(inv)
        -- Must have equipped, don't try to acquire
        inv:item({name = "Teleport tablet"}, {
            amount = 5,
            source = loadout.ItemSource.NO_ACQUIRE
        })
        
        -- Only buy from GE, don't check bank
        inv:item({name = "Super attack(4)"}, {
            amount = 2,
            source = loadout.ItemSource.GE_ONLY
        })
        
        -- Only from bank, never buy
        inv:item({name = "Dragon scimitar"}, {
            amount = 1,
            source = loadout.ItemSource.BANK_ONLY
        })
        
        -- Auto mode (default): try bank first, then GE if enabled
        inv:item({name = "Shark"}, {
            amount = 10,
            source = loadout.ItemSource.AUTO
        })
        
        -- With restock amount: require 100, but withdraw 150 each time
        inv:item({name = "Prayer potion(4)"}, {
            amount = 100,
            restock_amount = 150,
            noted = true
        })
    end)
    :settings(function(s)
        s.ge_enabled = true
        s.max_ge_cost_per_item = 5000
        s.max_ge_cost_total = 50000
    end)
    :build()

local result = loadout:apply(advanced_def)
if result.success then
    logger:info("Advanced loadout applied!")
elseif result.partial then
    logger:warn("Partial success. Missing:")
    for _, item in ipairs(result.missing_items) do
        logger:warn("  " .. item.item_name .. " (need " .. item.required .. ")")
    end
end

Result Types

Apply Result

{
    success = true,      -- Whether loadout was applied
    attempts = 2,        -- Number of attempts made
    reason = "...",      -- Error reason (if failed)
    partial = false,     -- True if partially applied
    missing_items = {    -- Items that couldn't be acquired (only present if partial=true)
        {
            item_id = 995,
            item_name = "Coins",
            required = 10000,      -- Target quantity (max for ranges)
            min_required = 5000,   -- Minimum required quantity
            available = 3000       -- Currently available quantity
        }
    }
}

Compliance Result

{
    compliant = false,
    missing_items = {
        {
            item_id = 995,
            item_name = "Coins",
            required = 10000,      -- Target quantity (max for ranges)
            min_required = 5000,    -- Minimum required quantity (for ranges)
            available = 3000        -- Currently available quantity
        }
    },
    extra_items = {1234, 5678}  -- Item IDs not in loadout
}

Missing Item Fields:

  • item_id (number) - Item ID
  • item_name (string) - Item name
  • required (number) - Target quantity to acquire (max for ranges)
  • min_required (number) - Minimum required quantity (for ranges, same as required for exact amounts)
  • available (number) - Currently available quantity in inventory/equipment

Related APIs

  • Bank API - Bank interface
  • Inventory API - Inventory management
  • Equipment API - Equipment management
  • ItemDefinitions API - Item cache lookups