Ikar BotHardShiftПланыКонтактыСкачать
IkarLabsIkar BotScript APIAPI объекта bot
API объекта bot

API объекта bot

Все свойства и методы L2Bot: что делает, какие параметры и что означают true и false.

На этой странице

Полный список того, что доступно скрипту через объект bot (тип L2Bot).

  • Свойства читают мир и возвращают модели — bot.user даёт Player, bot.npcs даёт List<Npc>. Поля этих классов описаны на странице Модели.
  • Командыsuspend-функции, все возвращают Boolean. Что именно означают true и false, написано для каждой команды отдельно.
  • log — единственный метод, который не suspend и ничего не возвращает.

Команды выполняются последовательно: вызов возвращает управление, когда команда отработала, — отдельно ждать после неё не нужно. Автоповтора нет: false — это ответ, а не ошибка, повторять или нет решает скрипт.

Оглавление

Про то, чем id отличается от oid и почему у многих команд по три формы, — в разделе «id или oid».

Чтение мира

Свойства, не функции: suspend не нужен, обращаться можно сколько угодно раз. Каждое обращение отдаёт свежую картину мира, но полученный объект — снимок: сам он не обновляется, поэтому перечитывай свойство на каждой итерации цикла.

СвойствоТипЧто возвращает
bot.idStringИдентификатор персонажа, которым управляет скрипт.
bot.userPlayerСвой персонаж: HP/MP/CP, координаты, уровень, вес, адена, каст, инвентарь, умения.
bot.targetLiveEntity?Текущая цель. null — цели нет. Конкретный тип — Npc, Char, Player или Pet.
bot.npcsList<Npc>Все видимые NPC и мобы. Пустой список — рядом никого.
bot.charsList<Char>Все видимые другие игроки.
bot.dropsList<Drop>Весь видимый дроп на земле.
bot.petsList<Pet>Свои петы и саммоны. Сейчас 0 или 1 элемент.
bot.skillsList<Skill>Свои умения. То же самое, что bot.user.skills.
bot.inventoryList<InventoryItem>Свой инвентарь. То же самое, что bot.user.inventory.
bot.partyList<PartyMember>Участники группы. Пустой список — группы нет.
bot.dialogTextStringHTML текущего или последнего диалога NPC. Пустая строка — диалога не было.
bot.storeItemsList<StoreItem>Товары последней открытой частной лавки. Пусто — лавку не открывали.
bot.storeSellerOidIntЧья лавка лежит в bot.storeItems. 0 — лавку не открывали.
bot.boardTextStringHTML текущей или последней комьюнити-борды (кастомной панели). Пустая строка — борду не открывали.
bot.automationRunningBooleanРаботает ли встроенная автоматизация бота. Нужна, чтобы скрипт вернул её в исходное состояние, а не включил вслепую тому, у кого она не работала.
bot.eventsFlow<ScriptEvent>Поток игровых событий.
Kotlin
val me = bot.user                    // Player
bot.log("${me.name}: ${me.hp}/${me.maxHp} hp, ${me.adena} адены")

val mob = bot.npcs.nearest { it.attackable && !it.dead }   // Npc?
if (mob != null) bot.log("${mob.name}, ур. ${mob.level}, ${mob.distToSelf} ед.")

Цель и бой

МетодЧто делаетЧто возвращает
setTarget(id: Int): BooleanВыбирает цель. id — template-id моба (берётся ближайший живой такого типа) либо object id.true — цель выбрана. false — объекта нет либо сервер цель не подтвердил.
setTarget(entity: LiveEntity): BooleanВыбирает цель по сущности.true — цель выбрана. false — объекта уже нет в мире.
setTargetByOid(oid: Int): BooleanВыбирает цель строго по object id.true — цель выбрана. false — объекта нет.
setTargetByType(npcId: Int): BooleanВыбирает ближайшего живого моба указанного типа.true — цель выбрана. false — моба такого типа рядом нет.
cancelTarget(): BooleanСнимает текущую цель.true — цель снята. false — снять не удалось.
attack(ctrl: Boolean = false): BooleanАтакует текущую цель. ctrl — атака с зажатым Ctrl (форс).Всегда true — атака отправлена. Попала ли она, смотри по событиям AttackStarted/Died или по HP цели.
attack(target: LiveEntity, ctrl: Boolean = false): BooleanВыбирает цель, затем атакует.Всегда true. Результат выбора цели не проверяется — см. заметку ниже.
attack(id: Int, ctrl: Boolean = false): BooleanТо же, цель — template-id либо object id.Всегда true.
forceAttack(target: LiveEntity, ctrl: Boolean = false): BooleanФорс-атака по сущности.Всегда true — атака отправлена.
forceAttack(id: Int, ctrl: Boolean = false): BooleanФорс-атака по template-id (ближайший живой) либо object id.Всегда true.
forceAttackByOid(oid: Int, ctrl: Boolean = false): BooleanФорс-атака строго по object id.Всегда true.
assist(other: LiveEntity): BooleanБерёт цель указанного персонажа.true — цель взята. false — персонажа не видно либо у него нет цели.
assistByOid(oid: Int): BooleanТо же строго по object id.true — цель взята. false — объекта с таким oid не видно.
assist(name: String): BooleanБерёт цель персонажа с указанным именем.true — цель взята. false — персонажа с таким именем не видно.
autoTarget(range: Int = 2500, zRange: Int = 500): BooleanСам находит и берёт в цель ближайшего врага: в радиусе range и в пределах zRange по высоте.true — враг найден и взят в цель. false — подходящих врагов нет.
ignore(id: Int): BooleanДобавляет в игнор-лист. id — template-id (добавляются все видимые сейчас мобы этого типа) либо object id.Всегда true — записи добавлены.
ignore(entity: LiveEntity): BooleanДобавляет в игнор-лист конкретную сущность.Всегда true.
ignoreByOid(oid: Int): BooleanТо же строго по object id.Всегда true.
clearIgnore(): BooleanОчищает игнор-лист.Всегда true.
stopCasting(): BooleanПрерывает собственный каст.true — прерывание отправлено и принято. false — прервать не удалось.

Игнор-лист держится по объектам, а не по типам. ignore(templateId) добавит всех мобов этого типа, которые видны в момент вызова; те, что заспавнятся позже, в игнор не попадут — вызывай снова.

У форм с целью результат выбора цели не проверяется. attack(mob) — это «выбрать цель, затем атаковать», и true относится только к отправке атаки. Если важно убедиться, что цель выбралась:

Kotlin
if (bot.setTarget(mob)) bot.attack()

Умения

МетодЧто делаетЧто возвращает
castSkill(skillId: Int, target: LiveEntity? = null, ctrl: Boolean = false, shift: Boolean = false): BooleanКастует умение. target = null — по текущей цели. ctrl — форс-каст (Ctrl), shift — каст без подхода к цели (Shift).true — каст начался. false — умения нет, оно на перезарядке, не хватает MP, персонаж сидит или сервер каст отклонил.
castSkill(skillId: Int, targetId: Int, ctrl: Boolean = false, shift: Boolean = false): BooleanТо же; цель — template-id моба (ближайший живой) либо object id.Как выше.
castSkillByOid(skillId: Int, targetOid: Int? = null, ctrl: Boolean = false, shift: Boolean = false): BooleanТо же; цель строго по object id, null — текущая цель.Как выше.
castAttackSkill(skillId: Int, target: LiveEntity? = null, ctrl: Boolean = false, shift: Boolean = false): BooleanКастует атакующее умение. Для боевых скиллов бери этот метод, для остальных — castSkill.true — каст начался. false — те же причины, что у castSkill.
castAttackSkill(skillId: Int, targetId: Int, ctrl: Boolean = false, shift: Boolean = false): BooleanТо же; цель — template-id либо object id.Как выше.
castAttackSkillByOid(skillId: Int, targetOid: Int? = null, ctrl: Boolean = false, shift: Boolean = false): BooleanТо же; цель строго по object id.Как выше.
castSkillAt(skillId: Int, x: Int, y: Int, z: Int, ctrl: Boolean = false, shift: Boolean = false): BooleanКастует умение по точке на земле (для скиллов с выбором места).true — каст начался. false — умение недоступно либо сервер отклонил.
dispel(skillId: Int): BooleanСнимает с себя указанный бафф — как клик по его иконке.true — бафф снят. false — такого баффа нет либо снять не удалось.

Если цель передана явно, она сначала выбирается, и только потом идёт каст.

Проверить умение перед кастом можно по Skillskill.ready означает «не на перезарядке, не пассивное, не заблокировано», но MP не учитывает:

Kotlin
val nuke = bot.user.skill(1177)
if (nuke != null && nuke.ready && bot.user.mp > 100) bot.castAttackSkill(nuke.id, mob)

Сидящий персонаж не кастует — сначала stand().

Предметы

pet = true означает «работать с инвентарём пета».

МетодЧто делаетЧто возвращает
useItem(id: Int, pet: Boolean = false): BooleanИспользует вещь. id — template-id вещи либо object id конкретной вещи.true — вещь использована. false — вещи нет в инвентаре либо использовать её нельзя.
useItem(item: InventoryItem, pet: Boolean = false): BooleanИспользует конкретную вещь из инвентаря.Как выше.
useItemByType(itemId: Int, pet: Boolean = false): BooleanСтрого по template-id.Как выше.
useItemByOid(oid: Int, pet: Boolean = false): BooleanСтрого по object id.Как выше.
dropItem(id: Int, count: Long): BooleanВыбрасывает вещь на землю. id — template-id либо object id.true — вещь выброшена. false — вещи нет в инвентаре либо её нельзя выбросить.
dropItem(item: InventoryItem, count: Long): BooleanТо же для конкретной вещи.Как выше.
dropItemByOid(oid: Int, count: Long): BooleanСтрого по object id.true — вещь выброшена. false — вещи с таким oid в инвентаре нет.
destroyItem(id: Int, count: Long): BooleanУничтожает вещь. id — template-id либо object id.true — вещь уничтожена. false — вещи нет либо её нельзя уничтожить.
destroyItem(item: InventoryItem, count: Long): BooleanТо же для конкретной вещи.Как выше.
destroyItemByType(itemId: Int, count: Long): BooleanСтрого по template-id.true — вещь уничтожена. false — вещи этого типа в инвентаре нет.
destroyItemByOid(oid: Int, count: Long): BooleanСтрого по object id.true — вещь уничтожена. false — вещи с таким oid в инвентаре нет.
crystallizeItem(id: Int): BooleanКристаллизует вещь. id — template-id либо object id.true — кристаллизация запущена. false — вещи нет либо персонаж не умеет кристаллизовать (user.canCrystallize).
crystallizeItem(item: InventoryItem): BooleanТо же для конкретной вещи.Как выше.
crystallizeItemByOid(oid: Int): BooleanСтрого по object id.Как выше.
transferItem(itemId: Int, count: Long, toPet: Boolean): BooleanПередаёт вещь между персонажем и петом. toPet = true — персонаж → пет, false — пет → персонаж.true — передача выполнена. false — вещи нет, пета нет либо передавать её нельзя.
transferItem(item: InventoryItem, count: Long, toPet: Boolean): BooleanТо же для конкретной вещи.Как выше.
craftItem(recipeId: Int): BooleanИзготавливает предмет по рецепту.true — крафт запущен. false — нет рецепта, материалов или MP.
setAutoShots(itemId: Int, enabled: Boolean, pet: Boolean = false): BooleanВключает или выключает автоматические шоты указанного типа. pet = true — шоты пета.true — настройка применена. false — шотов этого типа нет в инвентаре.
setAutoShots(item: InventoryItem, enabled: Boolean, pet: Boolean = false): BooleanТо же по вещи из инвентаря.Как выше.

count во всех операциях с количеством — Long.

Движение

У скрипта два способа перемещения, и они очень разные.

МетодЧто делаетЧто возвращает
moveToByGeo(x: Int, y: Int, z: Int, timeoutMs: Long = 15_000): BooleanВедёт персонажа в точку по проходимой геодате сервера, огибая препятствия. Блокирует скрипт до конца ходьбы.true — персонаж дошёл. false — пути нет, встал намертво, сработал stopMove(), истёк таймаут либо двигаться нельзя (мёртв, сидит).
moveToByGeo(target: Positioned, timeoutMs: Long = 15_000): BooleanТо же, но цель — сущность или дроп (берутся их координаты).Как выше.
stopMove(): BooleanПрерывает идущую ходьбу — выполняющийся moveToByGeo немедленно вернёт false.Всегда true — команда отмены отправлена.
moveTo(x: Int, y: Int, z: Int, timeoutMs: Long = 8000): BooleanОтправляет одно прямое перемещение в точку и ждёт прибытия. Препятствия не огибает.true — персонаж оказался в точке (≈80 единиц по X/Y) до истечения таймаута. false — не успел: упёрся, слишком далеко либо не двинулся вовсе.
moveTo(target: Positioned, timeoutMs: Long = 8000): BooleanТо же к сущности или дропу.Как выше.
moveToNoWait(x: Int, y: Int, z: Int): BooleanПрямое перемещение без ожидания прибытия.Всегда true — перемещение отправлено. Дошёл ли персонаж, проверяй сам по bot.user.x/y.
moveToNoWait(target: Positioned): BooleanТо же к сущности или дропу.Всегда true.

moveToByGeo — рабочий способ ходить по миру

Команда блокирующая: управление вернулось — значит персонаж уже пришёл (true) либо уже никуда не идёт (false).

  • timeoutMs — верхний предел ожидания, по умолчанию 15 секунд. Для длинного маршрута ставь больше или 0без дедлайна.
  • Зависнуть навсегда даже без таймаута нельзя: если персонаж перестал двигаться, маршрут перестраивается, а когда попытки исчерпаны — команда возвращает false.
  • Каст и обездвиживание пережидаются внутри команды — прерывать её из-за них не нужно.
  • Ограничения зон персонажа (рабочая область, запретные области) на маршрут не влияют: сказано «иди туда» — идём.
  • Новый вызов вытесняет предыдущую ходьбу, а не встаёт за ней в очередь.

moveTo / moveToNoWait — один шаг напрямую

Отправляют одно перемещение по прямой. На открытом месте или для короткого шага — быстро и достаточно; в стену персонаж упрётся и moveTo вернёт false по таймауту. Прибытие в moveTo проверяется по X/Y, высота не учитывается.

Kotlin
// дойти до дальней точки: автоматизацию лучше выключить, дедлайн снять
bot.disableAutomation()
val ok = bot.moveToByGeo(82000, 148000, -3470, timeoutMs = 0)
bot.log(if (ok) "пришёл" else "не дошёл")

Состояние персонажа

МетодЧто делаетЧто возвращает
sit(): BooleanСадится.true — персонаж сел. false — сесть нельзя (в бою, мёртв) либо сервер отказал.
stand(): BooleanВстаёт.true — персонаж встал. false — встать не удалось.
dismissPet(): BooleanОтзывает пета.true — пет отозван. false — пета нет либо отозвать не удалось.
dismissSummon(): BooleanРаспускает саммона или сервитора.true — саммон распущен. false — саммона нет либо распустить не удалось.
restart(): BooleanВыходит на экран выбора персонажа и дожидается его.true — экран выбора появился. false — не дождались либо выйти нельзя.
restartNoWait(): BooleanТо же, но без ожидания экрана.true — команда отправлена. false — отправить не удалось.
selectCharacter(slot: Int): BooleanВходит в мир персонажем из слота slot (нумерация с нуля). Только с экрана выбора — из игры сперва restart().true — вход состоялся. false — клиент не на экране выбора, слота нет либо ответа не дождались.
goHome(restartType: RestartType = RestartType.TOWN): BooleanВоскрешает персонажа или возвращает его в выбранную точку.true — возрождение выполнено. false — точка недоступна либо персонаж жив.

Значения RestartType: TOWN · CLAN_HALL · CASTLE · FORTRESS · FLAG.

Смена персонажа — это restart() и следом selectCharacter(n):

Kotlin
if (bot.restart() && bot.selectCharacter(2)) {
    bot.log("Теперь играем за ${bot.user.name}")
}

После успешной смены мир — другой персонаж: user, инвентарь, скиллы и окружение не имеют ничего общего с прежними. Перечитай bot.* целиком, а всё, что запомнил до смены (oid-ы, цели, дропы), выбрось.

Сидя персонаж не кастует умения — если скрипт сажает его на реген, не забудь stand() перед боем.

Диалоги NPC

МетодЧто делаетЧто возвращает
openDialog(): BooleanОткрывает диалог с текущей целью. Цель не перевыбирается — она уже должна быть выбрана.true — NPC ответил диалогом. false — цели нет либо диалога не последовало.
openDialog(id: Int): BooleanВыбирает NPC и открывает диалог. id — template-id (ближайший живой такого типа) либо object id.true — NPC ответил диалогом. false — NPC не найден либо диалога не последовало.
openDialog(npc: Npc): BooleanТо же для конкретного NPC.Как выше.
openDialogByOid(npcOid: Int): BooleanСтрого по object id.Как выше.
selectDialog(option: String): BooleanВыбирает пункт диалога по подписи — по тексту, который виден в окне. Регистр не важен; сперва ищется точное совпадение, потом вхождение. Ждёт ответа сервера примерно до 2,5 секунд.true — пункт выбран, пришёл новый диалог. false — пункта с такой подписью нет либо ответа не дождались.
selectDialog(number: Int): BooleanВыбирает пункт по порядковому номеру: первый пункт — 1, второй — 2 и так далее. Считаются все кликабельные пункты диалога, сверху вниз.true — пункт выбран. false — такого номера в диалоге нет.
sendBypass(cmd: String): BooleanОтправляет команду диалога напрямую, без поиска пункта.Всегда true — команда отправлена. Ответ придёт событием DialogReceived.
selectBoard(option: String): BooleanНажимает кнопку комьюнити-борды (кастомной панели: бафер, телепорт, шоп) по её подписи. Регистр не важен: сперва точное совпадение, потом вхождение.true — кнопка нажата, панель прислала новую страницу. false — кнопки с такой подписью нет либо ответа не дождались.
selectBoard(number: Int): BooleanТо же по порядковому номеру: первая кнопка — 1. Считаются все кликабельные пункты страницы, сверху вниз.true — кнопка нажата. false — такого номера на странице нет.
confirmDialog(msgId: Int, requestId: Int, accept: Boolean): BooleanОтвечает на окно-вопрос. msgId и requestId берутся из события ConfirmDialogReceived.Всегда true — ответ отправлен.

HTML текущего (или последнего) диалога лежит в bot.dialogText; пустая строка — диалога не было.

Kotlin
if (bot.openDialog(30080)) {
    bot.selectDialog("Teleport")
    delay(300)
    bot.selectDialog(1)          // первый пункт открывшегося списка
}

Частные лавки

Лавка игрока — не диалог: сервер отдаёт её содержимое только по запросу, поэтому есть одна команда, которая делает всю дорогу целиком.

МетодЧто делаетЧто возвращает
openStore(seller: Char): BooleanПодходит к продавцу и открывает его лавку. Идёт по геодате, тем же каналом, что moveByGeo.true — товары пришли и лежат в bot.storeItems. false — продавца нет, не дошли либо ответа не было.
openStoreByOid(sellerOid: Int): BooleanТо же строго по object id.Как выше.

У обоих есть walkTimeoutMs (по умолчанию 15 с) на дорогу и timeoutMs (5 с) на ответ.

Товары не приходят возвращаемым значением — читай их из bot.storeItems сразу после true. Этот список — снимок на момент открытия, а не живые цены: когда кто-то выкупит позицию, сервер об этом молчит.

Kotlin
val seller = bot.chars.nearest { it.storeType == 1 } ?: return
if (bot.openStore(seller)) {
    bot.storeItems
        .filter { it.price < it.basePrice }        // дешевле базовой
        .forEach { bot.log("${it.itemId}: ${it.price} против ${it.basePrice}") }
}

Комьюнити-борда

Кастомные панели (бафер, телепорт, донат) — это не диалог NPC: у них своё окно, своя разметка в bot.boardText и свои команды selectBoard. Смешивать нельзя, selectDialog панель не видит.

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

Kotlin
bot.sendBypass("_bbshome")   // открыть борду; эта команда постоянная
delay(500)
bot.selectBoard("Buffer")    // раздел бафов
delay(500)
bot.selectBoard("Might")

Длинная страница приезжает несколькими пакетами; selectBoard дожидается её целиком, так что следующая команда уже видит полную разметку. Если кнопка требует ввода в поле (в разметке это $name в конце команды) — selectBoard её не заполнит, тут нужен sendBypass("<код> значение") вручную.

Группа

МетодЧто делаетЧто возвращает
inviteParty(name: String, lootMode: LootMode = LootMode.FINDERS_KEEPERS): BooleanПриглашает игрока в группу с выбранным режимом дележа лута.Всегда true — приглашение отправлено. Принял ли игрок, видно по событию PartyMemberJoined или по bot.party.
leaveParty(): BooleanВыходит из группы.true — группа покинута. false — персонаж не в группе.
setPartyLeader(member: PartyMember): BooleanПередаёт лидерство участнику группы.true — передача отправлена. false — участника с таким oid не видно.
setPartyLeader(oid: Int): BooleanТо же по object id участника.Как выше.
setPartyLeaderByOid(oid: Int): BooleanТо же, явная форма.Как выше.
setPartyLeader(name: String): BooleanПередаёт лидерство по имени игрока.Всегда true — передача отправлена.

У участников группы нет template-id — число в setPartyLeader(oid) всегда трактуется как object id (member.oid).

Значения LootMode: FINDERS_KEEPERS · RANDOM · RANDOM_SPOIL · BY_TURN · BY_TURN_SPOIL.

Приглашение к себе в группу приходит событием PartyInviteReceived, ответ на него — confirmDialog.

Чат

МетодЧто делаетЧто возвращает
say(text: String, channel: Int = 0, target: String = ""): BooleanОтправляет сообщение в чат. target — имя адресата, нужен только для привата.Всегда true — сообщение отправлено.

Коды каналов:

КодКаналКодКанал
0обычный (вокруг)8торговый
1крик9альянс
2приват (нужен target)10объявление
3группа11лодка
4клан13поле битвы
5GM14командный канал
6петиция (игрок)25друзья
7петиция (GM)
Kotlin
bot.say("готов")                                  // вокруг
bot.say("иду к вам", channel = 3)                 // в группу
bot.say("привет", channel = 2, target = "Friend") // в приват

Лут

МетодЧто делаетЧто возвращает
pickup(id: Int): BooleanПодбирает дроп. iditemId (берётся ближайший такой дроп на земле) либо object id дропа.true — вещь подобрана. false — дропа нет, он чужой, персонаж слишком далеко либо инвентарь переполнен.
pickup(drop: Drop): BooleanПодбирает конкретный дроп.Как выше.
pickupByOid(oid: Int): BooleanСтрого по object id дропа.Как выше.

Команда не подводит персонажа к дропу — подойти нужно самому. Сервер разрешает подбор только вплотную (порядка 50–80 единиц):

Kotlin
val drop = bot.drops.nearest { it.isMine } ?: return
if (drop.distToSelf > 60) bot.moveToByGeo(drop)
bot.pickup(drop)

Сырой пакет

Крайняя мера — на случай, когда типизированной команды для действия нет. Обычные методы этого раздела не заменяет и не дублирует: там пакет собирает сам игровой клиент, и он корректен по определению.

МетодЧто делаетЧто возвращает
sendPacket(hex: String, active: Boolean = false): BooleanОтправляет готовый игровой пакет — байты уходят на сервер как есть.true — клиент подтвердил отправку. false — пакет не ушёл либо исход неизвестен.
sendPacket(bytes: ByteArray, active: Boolean = false): BooleanТо же для пакета, собранного в коде.Как выше.

hex — тело пакета: опкод первым байтом, без префикса длины (длину и шифрование клиент допишет сам). Extended-пакет пишется целиком, вместе с D0 и подкомандой. Пробелы и запятые игнорируются, регистр любой.

Kotlin
bot.sendPacket("11 01")        // снять цель
bot.sendPacket("D0 0D 00 …")   // extended: D0 + подкоманда + тело

active = true — действию нужно активное окно клиента: окно будет выведено на передний план. Про доставку это не говорит ничего — сама отправка работает и в фоне.

Три вещи, которые стоит знать до того, как это использовать:

  • Содержимое не проверяет никто. Сервер на неверные байты обычно разрывает соединение.
  • true — это про клиента, не про сервер. Он значит «байты ушли на провод», а не «действие принято». Принял ли сервер — видно по событиям и по состоянию мира.
  • Повтор — на твоей совести. При false приложение сырой пакет не переотправляет: для неидемпотентной команды (купить, использовать вещь) второй заход означает второе выполнение.

Сырой трафик

Сниффер: пакеты как они есть на проводе, без разбора. Нужен для разведки — посмотреть, что клиент шлёт по кнопке, или поймать серверный пакет, которого нет среди событий.

Метод / полеЧто делаетЧто возвращает
capturePackets(incoming: Boolean = false, outgoing: Boolean = false): BooleanВключает или выключает захват. Заменяет прежнюю настройку целиком; вызов без аргументов выключает оба направления.true — применено. false — персонаж не найден.
packetsIn: Flow<Packet>Пакеты сервер→клиент.Поток; молчит, пока не включён захват.
packetsOut: Flow<Packet>Пакеты клиент→сервер — и команды бота, и то, что игрок сделал руками.Поток; молчит, пока не включён захват исходящих.

По умолчанию захват выключен, и это не забывчивость: в бою через провод идут десятки пакетов в секунду, и гнать их в скрипт без спроса незачем.

Kotlin
bot.capturePackets(incoming = true)
bot.packetsIn
    .filter { it.opcode == 0x0B }
    .collect { bot.log("${it.size} байт: $it") }

Захват снимается сам, когда скрипт заканчивается — забыть выключить не страшно.

Что в Packet

ПолеЧто это
hex: StringБайты пакета в hex, верхним регистром, без разделителей.
bytes: ByteArrayТе же байты.
opcode: IntПервый байт — опкод.
subOpcode: IntПодкоманда extended-пакета (после D0). -1, если пакет не extended.
size: IntДлина тела в байтах.
byteAt(index: Int): IntБайт по номеру, или -1 за пределами пакета.

Тело идёт целиком, опкод первым байтом и без префикса длины — ровно в том виде, в каком его принимает sendPacket.

Исходящие требуют перехвата

packetsOut устроен иначе, чем packetsIn: по умолчанию клиент вообще не отдаёт приложению то, что отправляет на сервер. capturePackets(outgoing = true) этот перехват поднимает, и он же поднимает его для записи профилей (game_buff, возврат на спот).

Перехват общий, поэтому он арендуется, а не переключается: выключение твоего захвата не оборвёт идущую параллельно запись, а её окончание не оборвёт твой поток.

Автоматизация и профили

Скрипт может управлять встроенной автоматизацией — той, что настраивается в приложении.

МетодЧто делаетЧто возвращает
enableAutomation(): BooleanВключает встроенную автоматизацию.Всегда true — переключение выполнено (если она уже включена, ничего не меняется).
disableAutomation(): BooleanВыключает встроенную автоматизацию.Всегда true.
loadZone(path: String): BooleanЧитает файл зон .iz (такой сохраняет приложение) и применяет его к персонажу.true — файл прочитан и зоны применены. false — файла нет, он не читается либо формат битый.
clearZone(): BooleanОчищает зоны персонажа.Всегда true — зоны очищены.
loadConfig(path: String): BooleanЧитает файл профиля настроек .json (такой сохраняет приложение) и применяет его к персонажу. Имя профиля берётся из имени файла.true — файл прочитан и отправлен на применение. false — файл не удалось прочитать.

path — обычный путь в файловой системе, абсолютный или относительно рабочего каталога приложения.

Вывод

МетодЧто делаетЧто возвращает
log(text: String)Пишет строку в лог скрипта. Не suspend, вызывается откуда угодно.Ничего (Unit).