rs2b0t docs

ManualScripting API › Items

Inventory, equipment and bank

Inventory & Equipment #

Inventory.items(): InvItem[]
Inventory.first(name: string): InvItem | null
Inventory.contains(name: string): boolean
Inventory.count(name: string): number   // total qty across stacks/slots
Inventory.countById(id: number): number // exact object ID across stacks/slots
Inventory.used(): number                // occupied slots
Inventory.free(): number                // unoccupied slots (0 if normal pack UI is unavailable)
Inventory.isFull(): boolean

Equipment.items(): InvItem[]
Equipment.contains(name: string): boolean
Equipment.equip(name: string): Promise<boolean>    // Wield/Wear/Equip from pack
Equipment.unequip(name: string): Promise<boolean>  // Remove into pack

InvItem #

class InvItem {
    name; id; slot; count;
    actions(): string[];
    interact(action: string): boolean | Promise<boolean>;   // held op, e.g. 'Bury', 'Eat'
    useOn(target: InvItem | Loc | Npc): boolean | Promise<boolean>;
}

While the bank is open, these queries read the bank's side-backpack component. Once populated, its counts and capacity remain authoritative even though the normal inventory tab is hidden. The side snapshot can populate one tick after the main bank component; Bank.withdrawX* waits for that handoff before recording its baseline. Side-view InvItem actions are the visible Deposit-* component buttons, and useOn returns false until the bank is closed.

useOn is "use X with Y" behind every processing skill, knife→logs, raw fish→range, ess→altar. Returns false if a loc target is off-scene.

const raw = Inventory.first('Raw shrimps');
const range = Locs.query().name('Range').within(3).nearest();
if (raw && range) await raw.useOn(range);

Bank #

Low-level bank UI. Prefer Banking.open to walk to and open a bank; use Bank.* once the interface is open.

Bank.isOpen(): boolean
Bank.ready(): boolean                     // the bank has said what it holds, empty included
Bank.waitReady(timeoutMs?, log?): Promise<boolean>
Bank.snapshotGeneration(): number         // take before a deposit
Bank.snapshotReady(): boolean             // the bank-side view has been captured
Bank.waitSnapshotAfter(gen, timeoutMs?): Promise<boolean>  // wait for the list that follows
Bank.loaded(): boolean                    // item list is non-empty; false for an empty bank
Bank.setNoteMode(on: boolean): Promise<void>
Bank.items(): BankItemSnapshot[]          // { slot, id, name, count, ops, comId }
Bank.count(name: string): number          // exact name, case-insensitive
Bank.countById(id: number): number        // when two objects share a display name
Bank.withdraw(name: string, op?: string): boolean | Promise<boolean>
Bank.withdrawById(id: number, op?: string): boolean | Promise<boolean>
Bank.withdrawX(name: string, count: number): Promise<boolean>   // Withdraw-X + dialog
Bank.withdrawXById(id: number, count: number): Promise<boolean>
Bank.withdrawLoad(name: string): Promise<boolean>               // All, else X for free slots
Bank.deposit(name: string, op?: string): boolean | Promise<boolean>
Bank.depositInventory(): Promise<void>
Bank.depositAllMatching(match: (name, id) => boolean, log?): Promise<void>
Bank.close(timeoutMs?: number): Promise<boolean> // waits for main + side modal halves
Bank.openBooth(stand, boothName, op, log?): Promise<boolean>
Bank.openNearest(boothName, op, log?): Promise<boolean>
Bank.openNearestAccess(access, log?): Promise<boolean>

// Pick a real withdraw label from item.ops ("Withdraw-All" vs "Withdraw All")
withdrawOp(ops, amount: 'all' | '10' | '5' | '1' | 'x' | 'any'): string | null

Gotchas

  • Bank.open* already waits for the item list, so count() / items() are good on the next line.
  • After a deposit ready() is already true and will not block. Take snapshotGeneration() before the deposit and wait on waitSnapshotAfter(gen).
  • Test emptiness with ready(), never loaded(). loaded() is "the list is non-empty", so an empty bank never satisfies it and a still-loading bank is indistinguishable from a drained one.
  • withdraw/deposit/count match names in full (case-insensitive). op is the context-menu label; use withdrawOp(item.ops, 'all') rather than hard-coding 'Withdraw-All'.
  • Prefer countById / withdrawById / withdrawXById when two objects share a display name.
  • Do not hand-roll walk + booth click in new scripts, use Banking.open.
if (!(await Banking.open({ stand: bankTile }))) return;
await Bank.depositAllMatching(depositAllExcept(['Harpoon', 'Fishing bait']));
await Bank.withdrawLoad('Fishing bait');
await Bank.withdrawX('Feather', 100);
// or by id when names collide:
// await Bank.withdrawById(someId, op);

See also #

Docs built from rs2b0t 100adccc 2026-09-02. Non-affiliation disclaimer. Built on the Lost City project.