Skip to content

API UO AttackNearest

Codex edited this page Sep 22, 2026 · 6 revisions

UO.AttackNearest

ClassicUO / Basic IDE

Home · Все команды · Константы и значения

Выбирает одну подходящую боевую цель и передаёт её обработчику атаки. Фильтры ограничивают допустимых персонажей; пользовательский classMask задаёт экипировку и приоритет классов, nearest — выбор внутри класса.

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

UO.AttackNearest(notoriety:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any, body:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any, body:Any, maxZ:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any, body:Any, maxZ:Any, nearest:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any, body:Any, maxZ:Any, nearest:Any, color:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any, body:Any, maxZ:Any, nearest:Any, color:Any, classMask:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any, body:Any, maxZ:Any, nearest:Any, color:Any, classMask:Any, aliveOnly:Any) -> Integer
UO.AttackNearest(notoriety:Any, distance:Any, body:Any, maxZ:Any, nearest:Any, color:Any, classMask:Any, aliveOnly:Any, visibleOnly:Any) -> Integer

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

Параметры

  • notoriety — Статус отношения к персонажу, полученный от сервера: 0 — неизвестный, 1 — Innocent, 2 — Ally, 3 — Gray, 4 — Criminal, 5 — Enemy, 6 — Murderer, 7 — Invulnerable. Число означает один статус; "5|6" или массив чисел — любой из перечисленных. Это не цвет одежды и не класс. Отрицательное число (обычно -1), 0xFFFF, "any", пустая строка или пустой массив отдельно отключают этот фильтр. Некорректная строка без допустимых чисел не находит никого. Порядок статусов приоритет не задаёт. Фильтр 5 выбирает Enemy, а не автоматически любого NPC/монстра; реальные значения зависят от сервера.
  • distance — Горизонтальный радиус в клетках включительно: 5 допускает расстояние 0..5. Расстояние — max(abs(dx),abs(dy)), поэтому соседняя диагональ тоже 1. По умолчанию или при отрицательном числе берётся UO.FindDistance(), а не безлимитный поиск. 0 оставляет ту же клетку X/Y. Не длина маршрута; препятствия и этажи этим параметром не проверяются.
  • body — Graphic тела персонажа/NPC, не ID конкретного персонажа и не type надетой брони. Число, hex-строка, строка "0x0190|0x0191" или массив чисел. 0x0190 (400) — мужчина-человек; 0x0191 (401) — женщина-человек. Маска объединяет оба тела. Список не включает автоматически другие расы, призраков или превращения; таблица стандартных тел. Отрицательное число (-1 по умолчанию), 0xFFFF, "any", пустая строка или пустой массив отдельно — любое тело. Неизвестный текст без допустимого числа даёт пустой результат.
  • maxZ — Максимум abs(Z цели - Z своего персонажа) включительно, в единицах Z мира. Это не число этажей и не клетки X/Y. maxZ=4 при Z игрока 10 допускает Z цели 6..14; 0 требует ровно одинаковую высоту. По умолчанию/при отрицательном числе берётся UO.FindVertical(). На лестнице равная Z может исключить нужную цель. Даже малая разность Z не доказывает доступность этажа.
  • nearest — true/1 по умолчанию выбирает ближайшего подходящего персонажа; равное расстояние разрешается меньшим serial. false/0 сохраняет первый подходящий объект в порядке списка клиента, не выбирает самого дальнего. При classMask сначала действует приоритет класса, затем расстояние внутри класса.
  • color — Hue самого mobile: Integer или числовая/hex-строка. Отрицательное число (-1 по умолчанию) и 0xFFFF — любой hue; 0 — именно hue 0, а не любое значение. Не цвет полоски notoriety и не оттенок одежды. Цвет надетой вещи этот параметр не проверяет.
  • classMask — Имена правил, заранее определённых UO.SetClassMask в этом же скриптовом runtime. Например "DTMH|охотник|запасной" — приоритет слева направо; также допускается массив строк. Названия любые, регистр не важен. Разделители строки: |, запятая или ;. Любое неизвестное имя/пустой элемент внутри списка отменяет выбор целиком: результат 0, атаки нет. Это не числовая битовая маска: 7 не значит три класса. Пропущенный аргумент, -1, "-1", "any", "all" или пустая строка отдельно отключают фильтр классов. Mage/Tank/Archer не встроены: без регистрации таких правил совпадений не будет.
  • aliveOnly — true/1 исключает mobiles с IsDead != 0; false/0 по умолчанию не добавляет это условие. Не сравнение HP с нулём, не поиск трупов-предметов и не гарантия, что цель останется живой после вызова.
  • visibleOnly — true/1 требует IsVisible=1 по текущему состоянию ClassicUO; false/0 по умолчанию не добавляет условие. Это видимость загруженного объекта клиенту, а не проверка стен/линии обзора. Для геометрической проверки есть отдельная UO.CheckLOS с координатами; сервер всё равно может отклонить действие.

Возвращает

Integer — serial выбранного mobile, либо 0, когда подходящей цели нет или classMask недействителен. Это не 1/0-флаг, не body/type, не расстояние и не подтверждение удара. Проверяйте enemy <> 0; enemy = true сравнивает ID с 1 и здесь неверно. При ненулевом ID обработчик ClassicUO ещё может показать подтверждение атаки Innocent; сервер может отклонить действие.

Поведение

  • Поиск локальный: только уже загруженные mobiles. Учитывается Ignore; self исключён, кроме явного includeSelf=true в поддерживающих его командах. Контейнеры и предметы не являются mobiles.
  • Условия применяются вместе (AND). Допустимые альтернативы внутри body/notoriety объединены через OR. Поиск не меняет FindItem, FindCount и GetFoundItems.
  • В body/notoriety маска с допустимыми числами использует именно их: "any|5" всё равно ограничивает значением 5. Пустые/неверные элементы рядом с допустимыми числами игнорируются. Для отсутствия ограничения передайте -1 отдельно. Не переносите это правило на classMask: неизвестное имя класса отклоняет весь список.
  • Команды не открывают область мира, не бегут к цели и не проверяют проходимость маршрута. Между выбором и обработкой сервером состояние мира может измениться.
  • Передача true и 1 равнозначна для флагов, false и 0 также. Другие ненулевые числа тоже преобразуются в true, но 8/9 не являются отдельными режимами; используйте понятные true/false.
  • Имя — пользовательская метка, а не серверная профессия. Можно назвать правило DTMH, моя_группа или любым другим словом. Движок не определяет навыки/класс на сервере по имени персонажа.
  • В required один type или плоский массив означает хотя бы одну вещь из списка. Массив групп означает: нужна хотя бы одна вещь из КАЖДОЙ группы. Например [кожа, посохи] требует кожу И посох. Это набор альтернатив, а не требование надеть весь перечисленный гардероб.
  • Любая надетая вещь из forbidden исключает персонажа из этого правила, даже при выполненных required. Кожа плюс запрещённый chain не проходит правило кожи. Другие правила продолжают проверяться.
  • Учитываются только загруженные вещи, надетые на слоях 1..24 кроме рюкзака 21. Содержимое рюкзака/сундука, маунт 25, магазин 26..28 и банк 29 не считаются одеждой. Сравнивается graphic/type; serial, имя и hue вещи здесь не используются.
  • Список без загруженной подходящей экипировки не совпадает. Отсутствие запрещённой вещи в локальных данных не доказывает её отсутствие на сервере, если сервер ещё не прислал экипировку. Клиент не угадывает скрытые данные.
  • Правила принадлежат одному runtime скрипта, включая его функции и Include; не передаются другим самостоятельным запускам и не сохраняются в профиль. При новом запуске определите их снова, например общей процедурой настройки. Повторный SetClassMask заменяет правило с тем же именем, только после полной проверки новых данных.
  • Массивы копируются при регистрации. Изменение исходного массива не меняет правило: повторите SetClassMask. Несколько совпавших правил разрешаются порядком имён в classMask. Никаких стандартных таблиц одежды сервера нет.
  • Поддерживаются 1..9 позиционных аргументов. Пропускать можно хвост; чтобы задать classMask, нужно передать первые шесть аргументов. Используйте именованные VAR, чтобы видеть смысл каждой позиции.
  • Выбирается одна цель, атака отправляется один раз. Это не автоматический цикл боя. Без classMask фильтр экипировки и чтение вещей не выполняются.
  • Сначала общие фильтры, затем приоритет слева направо, затем nearest. nearest=false всё равно сохраняет приоритет классов, но внутри первого подходящего класса выбирает первый mobile в списке клиента.
  • Старая попытка поиска подстроки в имени/титуле заменена правилами экипировки. Перенесите такие скрипты на явный SetClassMask; имя персонажа больше не выдаёт его за определённый класс.

Внутренние функции: последовательность выполнения

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

1. CompactAttackNearest

Разбирает девять позиционных значений и их значения по умолчанию.

Не создаёт собственный боевой цикл.

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

2. TryResolveClassRules

Один раз разрешает все имена в снимок правил. Неизвестное имя отклоняет весь список.

Никакой подмены пустым фильтром или поиском по имени mobile.

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

3. FilterMobiles

Исключает self/Ignore; проверяет distance, notoriety, body, maxZ, color, aliveOnly, visibleOnly.

Фильтры применяются до приоритета класса.

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

4. GetWornTypes

На игровом потоке за одно обращение снимает graphic надетых вещей.

Перебирает экипировку одного mobile, не все предметы мира; ничего не запрашивает у сервера.

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

5. SelectClassCandidate

Один проход по кандидатам: меньший номер класса, затем дистанция и serial.

Полная сортировка списка не нужна. При nearest=false сохраняется первый внутри класса.

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

6. Attack

Вызывает GameActions.Attack, включая штатное подтверждение потенциально криминальной атаки.

Возвращённый ID означает выбор цели, не успешный удар.

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

Стоимость зависит от числа загруженных кандидатов, их вещей и правил. Нет новых потоков, ожидания или сетевого опроса экипировки.

Примеры

Пример 1. Ближайший Enemy в пяти клетках: короткая форма

SUB Main()
    # 5 = Enemy по notoriety; второй 5 = радиус, это разные параметры.
    VAR enemy = UO.AttackNearest(5, 5)
    IF enemy = 0 THEN
        # В этом случае атаки не было.
        RETURN
    END IF
    # Запоминаем ID уже выбранной цели для следующих действий скрипта.
    UO.AddObject("combat_target", enemy)
END SUB

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

  • body=-1, maxZ=FindVertical(), nearest=true, color=-1, classMask отключён, aliveOnly=false, visibleOnly=false. Для обязательного исключения мёртвых используйте полную форму ниже.

Пример 2. Только заданные тела и та же высота: все флаги без классов

SUB Main()
    # Каждая переменная соответствует одной позиции вызова ниже.
    VAR status = "5|6"          # Enemy или Murderer, не 5-й/6 предмет.
    VAR radius = 8              # Радиус 8 клеток, не задержка.
    VAR bodies = "0x0190|0x0191" # Только эти два body; не тип брони.
    VAR heightTolerance = 0     # Z цели должен совпасть с Z игрока.
    VAR chooseNearest = true    # Ближайший из отфильтрованных.
    VAR bodyHue = -1            # Hue тела не ограничиваем; 0 означал бы hue 0.
    VAR equipmentClasses = -1   # Нет фильтра одежды/приоритета классов.
    VAR requireAlive = true
    VAR requireVisible = true
    VAR enemy = UO.AttackNearest(status, radius, bodies, heightTolerance, chooseNearest, bodyHue, equipmentClasses, requireAlive, requireVisible)
    IF enemy <> 0 THEN
        UO.AddObject("enemy_same_height", enemy)
    END IF
END SUB

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

  • maxZ=0 полезен для строгого сравнения высоты, но может отсечь цель на ступеньке. visibleOnly не проверяет стену. Все девять аргументов подписаны; возвращается ID, не true.

Пример 3. Свои названия, свои вещи и порядок атаки

FUNCTION Gear(ParamArray values())
    # Возвращает массив переданных значений, без поиска в игре.
    RETURN values
END FUNCTION

SUB Main()
    # Примерные graphic/type. Сверьте свои вещи через Info/GetType.
    # В списке только разрешённые вами типы, это не serial предметов.
    VAR leather = Gear(0x13C4, 0x13C7)
    VAR staves = Gear(0x0DF0, 0x0E81)
    VAR chain = Gear(0x13BF, 0x13C0)
    VAR plate = Gear(0x1415, 0x1411)
    VAR bows = Gear(0x13B2, 0x0F50)
    # DTMH: одна вещь из leather И одна из staves; chain запрещён.
    UO.SetClassMask("DTMH", Gear(leather, staves), chain)
    # охотник: одна вещь из bows; остальные вещи не ограничиваем.
    UO.SetClassMask("охотник", bows)
    # тяжёлый: хотя бы одна перечисленная пластинчатая вещь.
    UO.SetClassMask("тяжёлый", plate)

    VAR notoriety = "5|6"     # Enemy ИЛИ Murderer.
    VAR distance = 12         # До 12 клеток X/Y включительно.
    VAR body = -1             # Любое тело, не только human.
    VAR maxZ = 8              # Разница высот не больше 8 единиц Z.
    VAR nearest = true        # Ближайший ВНУТРИ первого доступного класса.
    VAR color = -1            # Любой hue тела, одежду по hue не фильтруем.
    VAR classMask = "DTMH|тяжёлый|охотник"
    VAR aliveOnly = true      # Отсеиваем мёртвых mobiles.
    VAR visibleOnly = true    # Видимых клиенту; это не CheckLOS.
    VAR enemy = UO.AttackNearest(notoriety, distance, body, maxZ, nearest, color, classMask, aliveOnly, visibleOnly)
    IF enemy = 0 THEN
        UO.Print("No matching enemy; no attack sent")
        RETURN
    END IF
    # AttackNearest уже направила цель в обработчик атаки; второй Attack не нужен.
    UO.AddObject("selected_enemy", enemy)
END SUB

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

  • Сначала выбирается DTMH; только если подходящих DTMH нет — тяжёлый, затем охотник. DTMH на 10 клетках имеет приоритет над тяжёлым на 2 клетках. Для обратного порядка поменяйте строку classMask. Из двух DTMH выбирается ближайший.
  • Gear — полностью приведённая пользовательская функция BASIC, не отдельная команда UO. Два массива в Gear(leather, staves) образуют две обязательные группы. Добавление типа в leather расширяет альтернативы; не требует надевать две кожаные вещи.

Пример 4. nearest=false: первый в списке, а не самый дальний

SUB Main()
    # Не нужен порядок по расстоянию; требуем Enemy, живой и видимый.
    VAR sortByDistance = false
    VAR target = UO.AttackNearest(5, 10, -1, 4, sortByDistance, -1, -1, true, true)
    IF target = 0 THEN
        RETURN
    END IF
    UO.AddObject("current_enemy", target)
END SUB

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

  • 10 — радиус, 4 — допустимая разность Z, оба -1 после флага отключают color и classMask. Порядок списка клиента не гарантирован между обновлениями мира. Для предсказуемой близости используйте true.

Пример 5. Переупорядочить пользовательские группы

FUNCTION Gear(ParamArray values())
    # Возвращает массив переданных значений, без поиска в игре.
    RETURN values
END FUNCTION

SUB Main()
    # Примерные graphic/type. Сверьте свои вещи через Info/GetType.
    # В списке только разрешённые вами типы, это не serial предметов.
    VAR leather = Gear(0x13C4, 0x13C7)
    VAR staves = Gear(0x0DF0, 0x0E81)
    VAR chain = Gear(0x13BF, 0x13C0)
    VAR plate = Gear(0x1415, 0x1411)
    VAR bows = Gear(0x13B2, 0x0F50)
    # DTMH: одна вещь из leather И одна из staves; chain запрещён.
    UO.SetClassMask("DTMH", Gear(leather, staves), chain)
    # охотник: одна вещь из bows; остальные вещи не ограничиваем.
    UO.SetClassMask("охотник", bows)
    # тяжёлый: хотя бы одна перечисленная пластинчатая вещь.
    UO.SetClassMask("тяжёлый", plate)

    # Та же одежда, но теперь охотник важнее DTMH.
    VAR priority = "охотник|DTMH|тяжёлый"
    VAR enemy = UO.AttackNearest(5, 12, -1, 8, true, -1, priority, true, true)
    IF enemy <> 0 THEN
        UO.AddObject("priority_enemy", enemy)
    END IF
END SUB

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

  • Меняется только порядок меток: никаких новых таблиц одежды или названий в клиенте добавлять не требуется. Чтобы запретить fallback на тяжёлого, удалите его из priority.

Clone this wiki locally