Перейти к содержимому

Разбор структуры

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

Этот раздел даёт краткий обзор настройки LightScript с точки зрения сопровождения, с акцентом на типичные места возникновения проблем и способы их обнаружения и исправления. Начнём с краткого разбора идеальной структуры LightScript, чтобы вы познакомились с кодом, затем перейдём к устранению неполадок и завершим разделом FAQ.

Базовая структура требует <head>, <body> и <script>. Все объявления счётчиков и элементов управления пользователя размещаются внутри <head>. Все объявления canvas принадлежат <body>. Всё остальное должно быть помещено в раздел <script>.

<head> — одна из наиболее критичных и сложных частей любого LightScript. Неверный элемент управления или счётчик здесь может вызвать циклические сбои или отключить себя и любые счётчики, объявленные после него.

При создании счётчиков необходимо обеспечить:

  • Идеальный синтаксис (во избежание сбоев и неработающих счётчиков)
  • Отсутствие дублирующихся имён счётчиков (дубликаты перезаписываются)
  • Счётчики не выходят за границы экрана (вызывает сбои и ошибки)
  • Отсутствие недостающих или лишних опций в счётчиках (приводит к сбоям)
  • Все счётчики включают настройки разрешения (обеспечивает стабильное поведение)

Наиболее распространённые форматы экрана:

  • 16:9 (3840x2160, 2560x1440, 1920x1080, 1600x900, 1366x768, 1360x768, 1280x720)
  • 16:10 (2560x1600, 1920x1200, 1680x1050, 1440x900, 1280x800)
  • 21:9 (5120x2160, 3440x1440)

По умолчанию используется разрешение 2560x1440.

Все LightScript должны поддерживать форматы 16:9, 16:10 и 21:9. Хотя 4:3 не занимает значительной доли нашей аудитории, его следует учитывать для будущей совместимости.

Пример структуры счётчика с несколькими настройками разрешения:

Расположение и размер счётчиков по умолчанию применяются ко всем другим разрешениям в той же пропорции экрана. Например, если счётчики настроены для 1600x900, они должны корректно работать для всех других разрешений 16:9. Однако есть исключения. Fortnite имеет несколько разных позиций счётчиков даже в рамках одной пропорции экрана, а некоторые пропорции сами по себе могут вводить в заблуждение. Например, 1366x768 — распространённое разрешение во всём мире — часто указывается как 16:9, но фактически им не является. Аналогично, ультраширокие форматы 21:9 редко соответствуют своим номинальным размерам. По опыту работы в качестве разработчика интеграций, я никогда не встречал точного разрешения 21:9, несмотря на маркировку. Поэтому каждое ультраширокое разрешение должно быть создано, протестировано и настроено индивидуально.

Все настройки должны быть размещены между открывающим тегом <meta> и закрывающим </meta>; иначе они не будут работать. Если счётчик по умолчанию основан на 16:9 и стабильно работает для этих разрешений, добавлять настройки для других 16:9 разрешений не нужно. Однако необходимо добавить записи для каждого разрешения в других пропорциях (таких как 16:10 и 21:9), даже если пропорция согласована.

Наконец, каждый счётчик, кроме OCR-счётчиков, требует диапазона HSL для срабатывания. Эти диапазоны могут осложняться такими факторами, как:

  • Прозрачные элементы интерфейса
  • Градиенты в цветовых областях
  • Эффекты искажения экрана
  • Открытие внутриигровых меню
  • Изменения интерфейса при разных разрешениях
  • Использование контроллера вместо клавиатуры
  • Запись видео, способная вносить артефакты сжатия

Базовые инструкции по HSL и нормализованным координатам рассмотрены в документации разработчика и не повторяются здесь. Тестирование счётчиков будет обсуждаться в разделе «Выявление проблем», но важно подчеркнуть: количество тестирования для идеальной проверки всех счётчиков вычисляется как (количество счётчиков) × (количество настроек разрешения) × (количество режимов игры) × (количество играбельных персонажей) × (длина средней игры). Это легко складывается в часы верификации на одну игру, особенно если тренировочные режимы или другие обходные пути недоступны.

ДЕРЖИТЕ СЧЁТЧИКИ ЭФФЕКТИВНЫМИ — наш стандарт — это совершенство.

Тег <body> — это место, где объявляется элемент canvas. Он всегда должен выглядеть примерно как в следующем примере. Фактический id canvas можно изменить, но убедитесь, что он правильно извлекается в скрипте.

Сэкономьте время — скопируйте и вставьте это.

В этом теге в каждой интеграции должны происходить четыре вещи:

  • Canvas извлекается и используется для создания двухмерного контекста.
  • Первоначальный цикл обновления задаёт значения счётчиков, затем вызывает себя повторно для их поддержания.
  • Цикл обновления поддерживает переменные пользовательского управления в актуальном состоянии.
  • Счётчики выполняют свои функции обратного вызова при стабилизации.

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

  1. Игровой интерфейс отображает информацию в виде цветных полос, кнопок, текстовых полей и т. д. SignalRGB захватывает эти данные несколько раз в секунду, но фактическая частота захвата сильно зависит от эффективности кода. Важно понимать: один бесконечный цикл или необъявленная переменная может сломать весь скрипт и даже вызвать сбой SignalRGB. Хуже того, легко написать код, который технически работает, но настолько неэффективен, что захватывает данные лишь 1-2 раза в секунду.
  2. Каждый счётчик, объявленный в <head>, должен быть максимально компактным и эффективным для снижения накладных расходов. Проводите вычисления заблаговременно и часто; счётчик, занимающий 25% экрана, никогда не будет эффективным. Для OCR-счётчиков захватывайте отдельные буквы, а не целые слова. Для полос здоровья и маны отслеживайте только необходимые сегменты. ДЕЛАЙТЕ СЧЁТЧИКИ КАК МОЖНО МЕНЬШЕ.
  3. Счётчики захватывают информацию, обновляющуюся с каждым циклом.
  4. Ранее мы рассмотрели определение класса Meter, который хранит данные счётчика и запускает обратный вызов при стабилизации информационного массива. В начале скрипта объявите все Meter в одном блоке. Можно организовать или расставить их по алфавиту — главное не рассыпать их по тысячам строк. В итоге вам потребуется корректировать значения стабильности, и тратить время на поиск места объявления — неэффективно.
  5. Внутри функции обновления эти счётчики будут получать значения из логики чтения экрана при каждом цикле. Их внутренняя логика оценивает стабильность и при её достижении запускает соответствующую функцию обратного вызова.
  6. Эти функции обратного вызова должны быть объявлены в скрипте, но вне функции обновления. Внутри них проверяйте состояние значений Meter (value, decreased, increased, diff) и используйте их для определения того, следует ли воспроизвести анимацию эффекта. Такая структура кода, в отличие от размещения всего непосредственно в цикле обновления, позволяет строить масштабируемые интеграции.

Теперь рассмотрим пример реального цикла.

  • Идёт игра в League of Legends, в которой доступные умения выделены ярко-жёлтым цветом.
  • При каждом цикле конкретный счётчик умения фиксирует этот цвет как значение «1», поскольку он полностью проходит диапазон HSL счётчика.
  • Это «1» передаётся в экземпляр Meter, привязанный к счётчику чтения экрана, и вставляется в информационный массив этого Meter.
  • Если каждое значение в массиве равно «1», он считается стабильным и активирует прикреплённую функцию обратного вызова эффекта. Эта функция также активировалась бы, если бы все значения были «0» или «.1»Meter заботится только о стабильности. Важно отметить, что функция обратного вызова не будет непрерывно активироваться, если Meter постоянно стабилен с одним и тем же значением — только стабильность с НОВЫМ значением активирует обратный вызов.
  • После выполнения функции обратного вызова производится ряд условных проверок — в данном случае нужно лишь проверить, равно ли Meter.value «0», что означает использование умения.
  • Поскольку значение Meter равно «1», эта проверка не проходит и эффект умения не воспроизводится.
  • Через несколько секунд умение активируется и жёлтая подсветка вокруг кнопки исчезает.
  • Новое значение счётчика — 0, которое передаётся в класс Meter.
  • После достижения стабильности обратный вызов активируется и наше условие выполняется — воспроизводится эффект умения. Задержка полностью зависит от длины массива Meter, задаваемой при его объявлении. Большая длина означает большую задержку и меньше ложных срабатываний, поэтому тестируйте до нахождения оптимального баланса.

Счётчики чтения экрана должны иметь простые, чёткие и описательные имена, всегда начинающиеся со строчной буквы. Называть счётчик полосы здоровья «healthBar» — отлично. Называть два счётчика «healthBarRed» и «healthBarGreen» при отслеживании разных цветов в одной области — тоже хорошо. Но называть маленький счётчик, появляющийся только во время ультимейта одного героя, чем-то вроде «hrO21_yes» — источник боли и страданий для всех, кто будет исправлять ваш код. Выяснение того, что отслеживает плохо названный крошечный счётчик, при невезении может занять буквально час наблюдения за отдельными пикселями — так что этого делать не стоит.

Экземпляры класса Meter должны начинаться с заглавной буквы и заканчиваться словом Meter. Примеры «Q_Meter», «TookDamageMeter» и «TowerDestroyedMeter» полностью допустимы. Они должны быть чётко отличимы от счётчиков, объявленных в разделе <head>.

Функции эффектов также должны именоваться максимально просто и описательно. В некоторых играх сотни таких функций, в других — менее десяти. Если несколько героев имеют уникальные умения, включайте имя героя в качестве префикса, например «SonaQ», «ChamberE» или «AshUlt». В League of Legends, например, есть функции «DragonEffect», «TowerEffect» и «Q_Effects», содержащие несколько условий и используемые несколькими счётчиками. Такое именование помогает и с оптимизацией для масштабирования.

Не допускайте орфографических ошибок. Если не уверены в написании — проверьте. Имена должны быть чёткими и читаемыми независимо от того, кто работает с кодом и сколько времени прошло. Алфавитная организация имён помогает быстрому поиску, особенно если этот раздел часто редактируется. Хотя такой уровень организации не требуется для работы кода, он существенно облегчает жизнь разработчикам, занимающимся сопровождением.