API UO ObjAtLayerEx - LIHACHTETAN/ClassicUO-BadNewbie-BasicIDE GitHub Wiki

UO.ObjAtLayerEx

UO API · Все команды · Constants & Special Values

Читает предмет/контейнер в заданном слое у указанного загруженного персонажа.

Точный синтаксис

UO.ObjAtLayerEx(LayerType:Any, PlayerID:Any) -> Integer

Выберите одну из зарегистрированных форм. Параметры передаются позиционно. Any означает значение BASIC с преобразованием внутри команды; Unit — отсутствие возвращаемого значения.

Параметры

  • LayerType — Числовой номер слоя 1..29. Принимается целое или числовая строка, например 26 или "0x1A". Строковые имена Rhand/ShopBuyRestock и bare-константы слоёв здесь не преобразуются в номера. Используйте число.
  • PlayerID — Serial персонажа/mobile, числом, hex-строкой или разрешаемым объектным именем, например "self"/"lasttarget". Graphic/type предмета или ID самого контейнера не подходят.

Возвращает

Integer: serial предмета/контейнера на слое либо 0 при пустом/неизвестном слое, недопустимом номере или отсутствии загруженного Mobile. Это не Boolean и не номер слоя.

Поведение

  • Чтение локальное, без target, покупки, открытия контейнера и сетевого запроса.
  • Проверяется диапазон 1..29. Конвертация неподходящего строкового параметра может вызвать ошибку; произвольное имя слоя не следует передавать вместо числа.
  • Для собственного персонажа со строковым именем слоя доступна отдельная UO.ObjAtLayer. Не путайте layer с world Z, индексом статики или координатой гампа.

Как это выполняется внутри

Ниже описана реализация этого движка. Имена внутренних методов не являются дополнительными командами BASIC.

1. ExecuteStealthCompatibility / Arg

Разрешает PlayerID и числовой LayerType.

Это общий преобразователь числа/serial, а не ConvertLayer.

Исходник проекта: external/InjectionScript/src/InjectionScript/Runtime/InjectionApiUO.cs; функция ExecuteStealthCompatibility / Arg.

2. ObjAtLayerEx / FindItemByLayer

На игровом потоке проверяет слой 1..29 и ищет Mobile по ID.

Возвращает serial из слота, иначе 0.

Исходник проекта: src/ClassicUO.Client/Game/Managers/ClassicUOInjectionApiBridge.cs; функция ObjAtLayerEx / FindItemByLayer.

В примерах показаны два разных владельца слоя и безопасная обработка отсутствующего результата.

Примеры

Пример 1. Получить магазинный контейнер и перечислить товары

SUB Main()
    # ShopBuyRestock: vendor layer 26 (0x1A). Сам ничего не покупает.
    # lasttarget должен содержать ID выбранного NPC-продавца.
    VAR vendor = lasttarget
    IF vendor = 0 THEN
        UO.Print("Vendor not selected")
        RETURN
    END IF

    # В ObjAtLayerEx передаётся числовой номер, не строка ShopBuyRestock.
    VAR shop = UO.ObjAtLayerEx(26, vendor)
    IF shop = 0 THEN
        UO.Print("ShopBuyRestock container is not loaded")
        RETURN
    END IF
    UO.Print("Shop container ID: " + CStr(shop))

    # Только уже загруженное непосредственное содержимое. Вложенности не обходятся.
    VAR items = UO.GetContent(shop)
    VAR i = 0
    WHILE i < GetArrayLength(items)
        VAR item = items[i]
        UO.Print(UO.GetName(item) + " | ID: " + CStr(item))
        UO.Print("Graphic: " + CStr(UO.GetType(item)))
        i = i + 1
    WEND
    UO.Print("Loaded entries: " + CStr(GetArrayLength(items)))
END SUB

Разбор параметров и выполнения:

  • LayerType=26; PlayerID=vendor; shop — serial контейнера. Для GetContent передаётся shop, а не номер слоя.
  • Массив индексируется с 0 до длины минус 1. Каждый элемент — serial. Пустой массив означает отсутствие загруженных непосредственных элементов; покупка не выполняется.

Пример 2. Отобрать товары нужного graphic и посчитать единицы

SUB Main()
    VAR vendor = lasttarget
    IF vendor = 0 THEN
        UO.Print("Vendor not selected")
        RETURN
    END IF
    VAR shop = UO.ObjAtLayerEx(26, vendor)
    IF shop = 0 THEN
        UO.Print("Shop layer is not loaded")
        RETURN
    END IF
    # Демонстрационный graphic ткани. Подставьте нужный graphic/type.
    VAR wantedType = 0x1766
    VAR stacks = 0
    VAR units = 0
    VAR items = UO.GetContent(shop)
    VAR i = 0
    WHILE i < GetArrayLength(items)
        VAR item = items[i]
        IF UO.GetType(item) = wantedType THEN
            stacks = stacks + 1
            # GetQuantity читает количество единиц в конкретном стеке.
            units = units + UO.GetQuantity(item)
        END IF
        i = i + 1
    WEND
    UO.Print("Stacks: " + CStr(stacks) + " | Units: " + CStr(units))
END SUB

Разбор параметров и выполнения:

  • wantedType — graphic, а item — ID отдельного предмета. stacks считает записи/стопки; units складывает количество в них.
  • Это чтение уже полученного количества, а не остаток, гарантированный будущей покупкой. Цена здесь не назначается.

Пример 3. Сравнить три магазинных слоя через полную процедуру

SUB Main()
    VAR vendor = lasttarget
    IF vendor = 0 THEN
        UO.Print("Vendor not selected")
        RETURN
    END IF
    # Каждый слой читается отдельно. Имена ниже — подписи, номера — параметры API.
    ShowVendorLayer(vendor, 26, "ShopBuyRestock / Rstk")
    ShowVendorLayer(vendor, 27, "ShopBuy / NRstk")
    ShowVendorLayer(vendor, 28, "ShopSell / Sell")
END SUB

SUB ShowVendorLayer(vendor, layerNumber, caption)
    VAR container = UO.ObjAtLayerEx(layerNumber, vendor)
    IF container = 0 THEN
        UO.Print(caption + ": not loaded")
        RETURN
    END IF
    VAR items = UO.GetContent(container)
    UO.Print(caption + " | Container ID: " + CStr(container))
    UO.Print("Loaded entries: " + CStr(GetArrayLength(items)))
END SUB

Разбор параметров и выполнения:

  • ShowVendorLayer объявлена целиком. vendor — ID NPC, layerNumber — 26/27/28, caption — только подпись.
  • Контейнеры могут быть неизвестны клиенту. 0 проверяется до GetContent: явный GetContent(0) означал бы запрос предметов на земле, что здесь не требуется.

Проверка примеров: скрипты загружены и выполнены в тестовом окружении движка с известными объектами и без выбранной цели/слоя. Отдельно проверены границы расстояния и высоты. Это не тест торговли на игровом сервере.