Project Clickable
документация · скрипты

Блок «JS код»

Гибрид визуального редактора и кода: скелет сценария собираете кубиками, а сложную логику, условия и переменные пишете на JavaScript в одном узле. Ниже — как это работает, полный справочник объекта ctx, готовые примеры и важные нюансы.

основы

С чего начать

Что это и зачем

StepType.Script

Блок «JS код» выполняет произвольный код на JavaScript. Он нужен там, где кубиков становится слишком много: сложные условия, арифметика, работа с переменными, свои циклы. Три строки кода часто короче десятка блоков.

Идея — смешивать: наглядные действия (ждать, кликать, скроллить) оставляйте кубиками, а ветвистую логику пишите кодом. Внутри кода доступ к автоматизации даёт объект ctx — через него ищут картинки, кликают, читают и меняют переменные.

Движок — Jint (JavaScript на чистом C#, встроен в программу). Отдельно ничего ставить не нужно. Поддерживается современный JavaScript: let/const, стрелочные функции, Math, строки, массивы.

Как добавить блок

  1. Откройте визуальный редактор сценария.
  2. В палитре слева найдите категорию «Переменные» → блок «JS код».
  3. Перетащите его на холст и соедините со Start (и с остальным графом).
  4. Двойной клик по узлу открывает редактор кода.

У узла один вход и один выход Out — он ведёт себя как обычный шаг.

Редактор кода

Окно редактора собрано под удобное написание кода:

Номера строкСлева; номер текущей строки подсвечен
Кнопка «Проверить»Проверяет синтаксис без запуска и показывает ошибку с позицией
Справочник ctxДвойной клик по методу — вставка в код, плейсхолдер сразу выделен
Переменные сценарияДвойной клик — вставка ctx.getNum("имя")
Правый клик по кодуМеню «Вставить ключ картинки» — ключ вставится в место клика
Tab / EnterTab = 2 пробела, Enter сохраняет отступ строки
Ctrl + колесоРазмер шрифта (или Ctrl++/)
Быстрый ввод вызова с картинкой: двойной клик по методу в справочнике (например ctx.findImage("имя")) — плейсхолдер "имя" выделится. Затем правый клик по нему → «Вставить ключ картинки» → выбранный ключ заменит плейсхолдер. Стирать ничего не нужно.

Кнопка «Проверить» ещё и вытаскивает из кода переменные, объявленные через ctx.setVar("имя", …), и показывает их в списке «Переменные сценария».

справочник

Объект ctx

Переменные

Общие для всего сценария: их видят и кубики, и другие JS-узлы.

ctx.getVar(имя)Значение переменной как есть (число/строка) или null
ctx.getNum(имя)Значение как число; 0, если нет или не парсится
ctx.setVar(имя, знач)Записать значение в переменную
ctx.has(имя)Есть ли такая переменная → true/false

Поиск картинок

Картинка задаётся ключом из реестра проекта — так же, как в кубиках.

ctx.findImage(ключ)Разовый поиск сейчас → true/false. Координаты попадают в foundX/foundY
ctx.findImage(ключ, порог)То же, со своим порогом совпадения0.8
ctx.waitImage(ключ, сек)Ждать появления до N секунд → true/false
ctx.waitImage(ключ, сек, порог)То же, со своим порогом0.8
Внимание: waitImage блокирующий — в параллельном мультиоконном режиме он тормозит остальные окна (см. раздел «Мультиоконный режим»).

Действия

ctx.click(x, y)Клик по координатам (с учётом окна)
ctx.move(x, y)Переместить курсор без клика
ctx.clickFound()Клик по последней найденной точке (после find/waitImage)
ctx.key("Enter")Нажать клавишу (Enter, F5, стрелки, буква…)
ctx.typeText("текст")Напечатать строку
ctx.delay(мс)Пауза в миллисекундах (прерывается стопом)

Результат поиска

Заполняются после findImage/waitImage и блоков поиска.

ctx.foundXX центра последней найденной картинки (-1, если нет)
ctx.foundYY центра последней найденной картинки
ctx.foundKeyКлюч последней найденной картинки
ctx.foundCountСколько точек нашёл последний «Найти все»

Окна и управление

ctx.bringToFront()Вывести текущее окно на передний план
ctx.stop()Остановить сценарий из кода

Прочее

ctx.log(...)Написать сообщение в лог сценария (окно отладки)
rand()Случайное число от 0 до 1 (напр. rand()*400)
практика

Примеры и нюансы

Клики и поиск

Найти картинку и кликнуть:

if (ctx.findImage("кнопка")) {
  ctx.clickFound();
}

Ждать до 10 секунд, кликнуть, иначе остановиться:

// ждём кнопку, кликаем со случайной задержкой
if (ctx.waitImage("кнопка", 10)) {
  ctx.clickFound();
  ctx.delay(500 + rand()*300);
} else {
  ctx.log("кнопка не появилась");
  ctx.stop();
}

Несколько вариантов по очереди (что найдётся первым):

if (ctx.findImage("согласиться")) {
  ctx.clickFound();
} else if (ctx.findImage("закрыть")) {
  ctx.clickFound();
} else {
  ctx.log("ни одного окна нет");
}

Найти, кликнуть и напечатать текст (например, в поле ввода):

if (ctx.findImage("поле_поиска")) {
  ctx.clickFound();
  ctx.delay(300);
  ctx.typeText("золотой меч");
  ctx.key("Enter");
}

Сложное условие (то, ради чего и нужен код):

var hp = ctx.getNum("hp");
var mana = ctx.getNum("mana");

if (hp < 30 && mana > 50) {
  ctx.findImage("хил") && ctx.clickFound();
} else {
  ctx.findImage("атака") && ctx.clickFound();
}

Циклы и повторы

Кликать, пока картинка на экране (собрать все награды):

// жмём «собрать», пока кнопка видна — но не более 20 раз
var n = 0;
while (ctx.findImage("собрать") && n < 20) {
  ctx.clickFound();
  ctx.delay(400);
  n++;
}
ctx.log("собрано раз: " + n);
Всегда ограничивайте цикл счётчиком (n < 20). Без предела while может крутиться вечно, если картинка не исчезает.

Повторить действие N раз:

for (var i = 1; i <= 5; i++) {
  ctx.key("Space");
  ctx.delay(300);
  ctx.log("выстрел " + i);
}

Задержки и человекоподобность

Случайная задержка (чтобы клики не были «по метроному»):

ctx.delay(800 + rand()*600);   // пауза 0.8–1.4 сек

Клик с небольшим разбросом вокруг точки:

// не точно в центр, а ±5 пикселей
var x = ctx.foundX + Math.round(rand()*10 - 5);
var y = ctx.foundY + Math.round(rand()*10 - 5);
ctx.click(x, y);

Иногда пауза подольше (имитация «отвлёкся»):

if (rand() < 0.1) {              // в 10% случаев
  ctx.log("длинная пауза");
  ctx.delay(3000 + rand()*2000);
}

Переменные и флаги

Счётчик и остановка по порогу:

ctx.setVar("кликов", ctx.getNum("кликов") + 1);

if (ctx.getNum("кликов") >= 10) {
  ctx.log("хватит");
  ctx.stop();
}

Флаг «первый запуск» (инициализация один раз):

if (!ctx.has("инициализирован")) {
  ctx.setVar("инициализирован", 1);
  ctx.setVar("золото", 0);
  ctx.log("первый запуск — обнулил счётчики");
}

Накопление и цель:

ctx.setVar("золото", ctx.getNum("золото") + 25);

if (ctx.getNum("золото") >= 1000) {
  ctx.log("цель достигнута: " + ctx.getNum("золото"));
  ctx.stop();
}

Связка с кубиками

Самый правильный паттерн (особенно для параллельного режима): ждать картинку — родным блоком «Ждать», а сразу после него поставить короткий JS-узел с логикой.

После блока «Ждать "враг"» — быстрая логика:

// картинка уже найдена блоком «Ждать», координаты в foundX/foundY
ctx.setVar("врагов", ctx.getNum("врагов") + 1);
ctx.clickFound();

if (ctx.getNum("врагов") % 5 == 0) {
  ctx.key("r");            // перезарядка каждые 5 врагов
}
Почему так лучше: ожидание висит на кубике (он в параллельном режиме отдаёт ход другим окнам), а скрипт делает только мгновенную логику — и не тормозит остальные окна.

Мультиоконный режим

Блок «JS код» работает в обоих режимах, и действия корректно попадают в нужное окно. Но есть разница:

ПоследовательныйПолностью нормально — окна и так идут по очереди. Любой код, любые ожидания.
ПараллельныйРаботает, но блокирующий код в скрипте тормозит остальные окна на время выполнения.
Почему так. Параллельный режим — кооперативный: окна по очереди получают ход и сами «отдают управление» на ожиданиях. Родной блок «Ждать» отдаёт ход другим окнам, а ctx.waitImage(..., 10) внутри скрипта — нет: он держит поток все 10 секунд, и остальные окна стоят.

Правило для параллельного режима: скрипт должен быть коротким и без долгих ожиданий.

  • Можно: findImage (мгновенная проверка), логика, setVar, один clickFound.
  • Избегать: waitImage, длинный delay, длинные циклы — они замораживают соседние окна.
  • Как надо: ожидание — родным блоком «Ждать», а скрипт ставить после него только для быстрой логики.

Ограничения и советы

Стоп работаетКлавиша стопа прерывает даже долгий цикл и delay в скрипте
Ошибки в логЕсли код упадёт — сообщение уйдёт в лог, узел вернёт «неуспех»
Проверяйте синтаксисКнопкой «Проверить» до запуска — сэкономит время
Ключи картинокТолько существующие из реестра проекта; берите правым кликом, чтобы не ошибиться в имени
Держите наглядностьБольшой сценарий лучше графом; код — для точечной логики