Loadout API
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
_notedfunctions - usenoted = truein config instead - Added
restock_amountto control withdrawal amounts - Added
sourcecontrol 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:
- Check current compliance
- Deposit extra items if strict mode enabled
- Withdraw missing items from bank
- Buy missing items from GE if enabled
- Equip equipment items
- Retry until compliant or max attempts reached
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
definition | LoadoutDefinition | Yes | Loadout to apply |
Returns:
table- Result with fields:success(boolean) - Whether loadout was applied successfullyattempts(number) - Number of attempts madereason(string, optional) - Error reason if failedpartial(boolean, optional) - True if partially appliedmissing_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:
| Parameter | Type | Required | Description |
|---|---|---|---|
definition | LoadoutDefinition | Yes | Loadout to check against |
Returns:
table- Compliance result with fields:compliant(boolean) - True if loadout requirements are metmissing_items(table) - Array of missing item infoextra_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:
| Parameter | Type | Required | Description |
|---|---|---|---|
callback | function | Yes | Function 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
callback | function | Yes | Function 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
callback | function | Yes | Function receiving settings table to modify |
Returns:
LoadoutBuilder- Self for chaining
Settings Table Fields:
| Field | Type | Default | Description |
|---|---|---|---|
strict_mode | boolean | false | Deposit extra equipment items not in loadout |
ge_enabled | boolean | false | Allow Grand Exchange purchases |
max_ge_cost_per_item | number | nil | Max cost per item from GE |
max_ge_cost_total | number | nil | Max total GE spending |
ge_price_multiplier | number | 1.5 | Price multiplier for GE offers |
ge_offer_wait_time_minutes | number | 5 | How long to wait for GE offers |
max_attempts | number | 5 | Max 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | table | Yes | Item filter (see Filter Options below) |
config | table | Yes | Configuration with fields: |
noted(boolean, optional) - Whether item should be noted (default: false)restock_amount(number, optional) - Override amount to withdraw/buy when restockingsource(string, optional) - Item source fromloadout.ItemSourceenum
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:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | table | Yes | Item filter |
config | table | Yes | Configuration with fields: |
max(number, required) - Maximum quantity allowednoted(boolean, optional) - Whether item should be notedrestock_amount(number, optional) - Override amount to withdraw/buysource(string, optional) - Item source fromloadout.ItemSourceenum
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:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | table | Yes | Item filter |
config | table | Yes | Configuration with fields: |
restock_amount(number, optional) - Override amount to withdraw/buysource(string, optional) - Item source fromloadout.ItemSourceenum
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:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | table | Yes | Item filter matching items to ignore |
config | table, optional | No | Configuration 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 theextra_itemslist 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 inextra_itemsat all.
EquipmentLoadoutBuilder Methods
item
eq:item(filter: table, config: table)
Add an equipment item using an item filter and configuration.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | table | Yes | Item filter (see Filter Options below) |
config | table | Yes | Configuration with fields: |
restock_amount(number, optional) - Override withdrawal/buy amountsource(string, optional) - Item source fromloadout.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:
| Parameter | Type | Required | Description |
|---|---|---|---|
filter | table | Yes | Item filter matching equipment items to ignore |
config | table, optional | No | Configuration 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 theextra_itemslist 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 inextra_itemsat all.
Filter Options
Item filters use the same format as inventory/bank filters:
| Filter | Type | Description |
|---|---|---|
id | number | Exact item ID |
ids | table | Array of item IDs to match |
name | string | Exact name match |
name_contains | string | Name contains text |
name_any | table | Match if name equals any in array |
name_contains_any | table | Match 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 IDitem_name(string) - Item namerequired(number) - Target quantity to acquire (max for ranges)min_required(number) - Minimum required quantity (for ranges, same asrequiredfor 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