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) означал бы запрос предметов на земле, что здесь не требуется.
Проверка примеров: скрипты загружены и выполнены в тестовом окружении движка с известными объектами и без выбранной цели/слоя. Отдельно проверены границы расстояния и высоты. Это не тест торговли на игровом сервере.