Space Engineers
40 оценки
Easy Play. Руководство по автоматизации
От Survival Ready
Руководство по автоматизации игрового процесса с помощью скрипта Easy Play
   
Награда
Добавяне към любими
В любими
Премахване от любими
Intro. Введение
The guide is written in Russian. Please use Google Translate[translate.google.com] for translation into other languages. You can also read the Easy Automation 2.0 manual, see examples and demo ships discussions topics to understand the basic principles of developing automation scripts. I am also ready to try in English to answer your questions related to the use of new commands in the discussions for this quide.
https://steamcommunity.com/sharedfiles/filedetails/?id=2688952356
Apart from the original
  • The absence of a separate LCD panel where automation code is placed in CustomData.
  • A more flexible syntax for if/else logic that does not require curly braces on a new line, as well as support for non-binary logic.
  • The ability to use dynamic variables anywhere in the expression.
  • The ability to override global variables in the code of any script.
  • A shortened syntax that disregards the case sensitivity for most properties and actions.
  • Detailed console debugging with error output for compilation and execution.
  • Robustness against crashes caused by typos and formatting errors in the code.
  • Easy localization to any language (not certain about Eastern and hieroglyphic languages).
  • The ability to work with grids and subgrids.
  • Handling of text data, including CustomData and editing fields of any screens.
  • Extended functionality, including data exchange via antennas, raycast lidar, inventory management, and the ability to create multi-level menus.
Demo ships
Most of the script's features are implemented in the ship's control scenario
https://steamcommunity.com/sharedfiles/filedetails/?id=2961122787
https://steamcommunity.com/sharedfiles/filedetails/?id=2993614241
Examples guides
Solving some tasks using Easy Play is described in other manuals in English
https://steamcommunity.com/sharedfiles/filedetails/?id=2967778856
https://steamcommunity.com/sharedfiles/filedetails/?id=2960637183
https://steamcommunity.com/sharedfiles/filedetails/?id=2944053111


Easy Play — это форк популярного скрипта Easy Automatition 2.0 который, к моменту написания данного руководства, являлся самым простым из всех существующих в Workshop скриптов автоматизации.

Код оригинального скрипта был полностью переписан и дополнен недостающим для меня функционалом, но общая концепция и основной синтаксис не изменились. Поэтому если вы раньше использовали Easy Automatition, то работа с Easy Play не должна вызвать проблем.

Для тех, кто сталкивается с автоматизацией впервые, скажу, что Easy Play позволяет реализовывать достаточно сложные сценарии типа запуска ракет, возврата к носителю по сигналу антенны, вывода инвентаря корабля на любой экран в нужном вам формате и т.п. без необходимости программирования скриптов на языке C#.

По сути, это альтернатива автоматизации на таймерах, но с возможностью выборочного анализа состояния игровых блоков и доступом к расширенному управлению ими. Например, с помощью Easy Play можно управлять гасителями, чего на таймерах запрограммировать нельзя.

От оригинала Easy Play отличает:
  • отсутствие отдельной LCD панели, в CustomData которой размещается код автоматизации

  • более свободный синтаксис логики if/else ,не требующий оформления фигурных скобок с новой строки, а так же наличие не бинарной логики

  • возможность использования динамических переменных в любом месте выражения

  • возможность переопределения глобальных переменных в коде любого сценария

  • сокращенный синтаксис без учета регистра написания большинства свойств и действий

  • наличие детальной консольной отладки с выводом ошибок компиляции и выполнения

  • устойчивость к краху программного блока из-за опечаток и ошибок оформления кода

  • простая локализации на любой язык (не уверен насчет восточных и иероглифических)

  • возможность работы с гридами и сабгридами

  • обработка текстовых данных, в т.ч. CustomData и полей редактирования любых экранов

  • расширенные функциональные возможности, включая обмен данными через антенну, Raycast-лидар, инвентаризацию и возможность создания многоуровневых меню.

Демонстрационные корабли
SE Mothership — основной корабль на котором представлено большинство команд Easy Play
SE Escape Pod — вспомогательный корабль, для демонстрации взаимодействия через антенну
SE Sputnic — реальный игровой процесс и взаимодействие с другими скриптами
SN Carrier — управление системой жизнеобеспечения (двери, шлюзы, мониторинг и т.п.)
Термины и определения
Автоматизация — код, который находится в поле "Свои данные" (далее CustomData) программного блока (далее ПБ) Easy Play

@-блок — именованная последовательность команд, заключенных в фигурные скобки, размещенная внутри кода автоматизации с помощью которой можно управлять состоянием игровых функциональных блоков — выдвигать поршни, открывать и закрывать двери и т.п. В коде автоматизации может быть любое количество @-блок (сценариев), которые можно вызывать через панель управления. Ниже представлено два таких сценария:
* вывод свойств и действий блока @show { Show \1 } * переименование блоков @rename { Rename \1 to \2 }

Блок переменных — специальный @-блок имя которого должно начинаться с var (без учета регистра), внутри которого определяются глобальные переменные используемые внутри сценариев автоматизации.
@Vars { pos = Position of MyPiston }

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

Консоль — данные поля "Редактировать" основного экрана ПБ Easy Play, куда в случае установленного режима отладки выводится ход выполнения вызванного через строку параметров @-блока

Локализация — данные поля "Редактировать" экрана клавиатуры ПБ Easy Play, где размещаются секции перевода системных сообщений, состояний блоков и названий игровых компонентов (руды, слитки и т.п.), если это поле пустое то используется английский язык

Панель управления - игровая системная панель, вызываемая на экран клавишей K которая дает доступ к списку функциональных блоков и управлению их свойствами и действиями (см. рисунок ниже).

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

Область Echo — область для вывода дополнительной системной информации о блоке, которая находится в правом нижнем углу панели управления. Easy Play также может использовать эту область для вывода своих сообщений по команде Echo.
@-блок автоматизации
@-блок или сценарий автоматизации всегда оформляется с новой строки, которая должна заканчиваться открывающий фигурной скобкой "{" и которой должна соответствовать закрывающая фигурная скобка "}".

В имени @-блока допускается использование прописных и строчных английских букв, цифр и символов "-" (минус), "_" (подчеркивание). Например:
@move_piston { UpperLimit of MyPiston = 7 Reverse MyPiston }
Выполнить сценарий можно указав имя @-блока в поле "Аргумент" ПБ Easy Play с учетом написания и нажав "Выполнить". Дополнительно в круглых скобках "()", через запятую "," можно указать параметры, к которым можно обратиться внутри @-блока по порядковому номеру.

Сценарий будет выполняться построчно, с учетом логики if/else, до тех пор, пока не будет достигнута конечная "}" скобка или в коде сценария не встретится команда Stop или End.
Запуск @-блока по ссылке
Один сценарий внутри своего кода может вызвать выполнение другого сценария. Сделать это можно по ссылке с использованием символа "@" за которым следует имя того @-блока, который нужно выполнить.

Например следующая автоматизация вызывает световое и текстовое оповещение если хотя бы одна турель Гатлинга обнаруживает цель.
@has_target { * если турель имеет цель If Status of Gatling = Target { * активируем сценарий тревоги @alert(Нападение противника) } else { * если нет, то сценарий отбой тревоги Exec @silent } } @alert { * установить режим мерцания ламп, объедиенных в группу Alert light Blink Interval of (Alert light) = 0.5 * вывести на LCD-панель надпись, переданную в сценарий первым параметром Write to LCD Alert = \1 } @silent { * отменить мерцание Blink Interval of (Alert light) = 0 * очистить LCD Write to LCD Alert = "" }

В отличии от Easy Automatition, Easy Play может вызывать другой @-блок по ссылке с параметром, который установит локальную переменную так, как если бы обращение к нему было из поля "Аргумент" программного блока. Это позволяет использовать один и того же сценарий в разных случаях.

Например, тревога на корабле может быть объявлена не только при нападении, но и при разгерметизации. В этом случае можно повторно использовать сценарий @alert, а в качестве параметра передать ему "Разгерметизация" вместо "Нападение противника".

Вызвать @-блок по ссылке можно в по полной форме, указав перед именем сценария ключевое слово Exec. Подобное оформление используется при обмене данных через антенну, чтобы избежать ошибок компиляции.
Свойства и действия
Внимание! Easy Play работает только с теми блоками, владельцем которых вы являетесь.
Каждый игровой блок имеет набор свойств и действий которые в игре вы можете установить либо напрямую через панель управления, либо через цифровую клавиатуру контроллера вынося на нее иконки блоков и задавая действия, которые с ней связаны.

Например для поршня можно вывести свойство "Верхний предел" и действие "Реверс". Тоже самое можно установить через панель управления при помощи соответствующего ползунка и кнопки. Это долго, гораздо проще обратиться к небольшому сценарию автоматизации, который сделает тоже самое без вызовов системных панелей:
@move_piston { * установить свойство "Верхний предел" UpperLimit of MyPiston = 7 * выполненить действия "Реверс" Reverse MyPiston }
Собственно в этом и заключается суть автоматизации — вместо того, чтобы искать в панели управления нужный вам блок и затем выносить на цифровую панель контроллера несколько связанных с ним иконок, достаточно в CustomData ПБ Easy Play написать сценарий в несколько строк и вынести на цифровую панель выполнение программного блока с заданным параметром, в данном случае — "move_piston".

Обращение к свойству блока производится с указанием ключевого слова of. Действие выполняется без указания ключевых слов — только команда и выборка блоков:
* установка свойства перехват управления для трастеров Override of Ion Thruster = 100% * выполнение команды включить перехват управления гироскопами Override Gyroscope

Дополнительно, в команде с помощью квадратных скобок можно указать количество блоков, к которым ее нужно применить
* перехватить управление двумя гироскопами Override[2] Gyroscope

Если имя свойства или команды состоит более чем из одного слова, то пробелы в ней нужно заменить на знак "-" (дефис)
* вывод в чат 3-го сообщения из блока Broadcast Controller Transmit-Message-3 Broadcast Controller * установит максимальную скорость для всех колес равной 150 Speed-Limit of Wheel = 150

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

Show[type] Имя_Блока, где в [] квадратных скобках можно указать одно из следующих значений: action — вывести только действия блока, info — вывести только дополнительную информацию и property — вывести только свойства блока. Все значения можно сократить до одной буквы: a, i, p

Без [] будет выведена вся доступная информация о блоке. Следующий сценарий выведет на экран всю информацию о блоке вентиляции имя которого начинается с Airvent:
@info { Show Airvent }
После выполнения этого сценария на экран консоли и в область Echo панели управления будет выведенная следующая информация (c вер. 1.33 свойства выводятся не через двоеточие, а через знак равенства):

.
Есть разница при выводе свойств блока в общем потоке, когда команда Show вызывается без [] квадратных скобок, и отдельно с указанием Show[property]. В последнем случае будет выведен не тип присваемого значения: True/False, Number или Color, а само значение. Это удобно для сохранения текущих установок и последующего их восстановления командой Set.
Типы данных
Есть 5 типов данных, которые определяются представлением переменной:

Логический тип — может иметь два значения True или False

Число (Number) — положительное или отрицательное число с десятичной точкой, граничные значения которого определяются игровыми свойствами блока. Например, верхний предел для поршня на большой сетке может быть числом от 0 до 10.

Цвет (Color) — RGB-представление триады цветов с разделителем ":", например 0:0:255 (синий цвет), где каждое значение есть целое положительное число от 0 до 255. В панели управления оно устанавливается при помощи трех ползунков или вводом значения для каждого цвета с использованием <Ctrl+ЛКМ> (левая кнопка мыши).

GPS-координаты — триада координат X:Y:Z с разделителем ":", например "-62664.81:-80178.37:-27915.08" где каждое значение может быть положительным или отрицательным числом с десятичной точкой.

Полный формат GPS-координат состоит из 6 частей и его можно увидеть в системном меню GPS, если скопировать любую GPS-метку в буфер обмена и затем вставить через <Ctrl+V> в любое текстовое поле, например: GPS:Base:-62664.81:-80178.37:-27915.08:#, где

GPS = обязательный префикс из трех английских прописных букв
Base = произвольное название точки координат
-62664.81 = координаты по оси Х, любое положительное или отрицательное цисло с "."
-80178.37 = тоже по оси Y
-27915.08 = тоже по оси Z
# = RGBA-представление цвета на экране (само значение можно опустить)

Обмен координатами через антенну и размещение их в списке точек назначения автопилота производится в полном формате.

Строка (String) — если значение отличается от выше перечисленных представлений, то оно считается строчным. Обычно для указания этого типа используются двойные кавычки ", но они необязательны, кроме представления многострочных значений или трансляции свойств блоков при выводе на экран (см. раздел "Запись и чтение LCD") и представления пустого значения. Ниже представлена инициализация и вывод на консоль трех строчных переменных
@vars { name = Ирокез type = "Ударный носитель" value = "" } @view { Console = "\name \N \type \value" }

Тип данных вы можете увидеть в свойствах блока. Например, при выводе свойств поршня по команде Show, они, в том числе, будут представлены следующими значениями:
* логический тип ShareInertiaTensor: True/False * число с десятичной точкой UpperLimit: Number
Любая переменная в @-блоке может переопределена и представлена любым типом данных, который, в свою очередь, может являться состоянием игрового блока, а так же условным или математическим выражением.
Типы переменных
Переменные Easy Play бываю двух видов:

глобальные, которые определяются в специальном @-блоке, начинающегося с @var и доступные для любого сценария внутри автоматизации. Блок @var должен быть первым блоком в поле CustomData, если предполагается использование глобальных переменных

локальные (динамические) которые создаются при запуске сценария из строки аргументов ПБ с перечислением через "," с использованием "()" (круглых скобок) и которые доступны только для того @-блока для которого они вызваны

Глобальные переменные
Обращение по имени. Имя переменной должно состоять из больших и маленьких английских букв, цифр и символов "-_". Вообще-то можно использовать и другие символы, в т.ч. русские, но для гарантии правильной обработки лучше придерживаться указанного выше правила.

Имена глобальных переменных не должны начинаться с цифр и не должны совпадать с зарезервированными системными словами типа if, on, at и т.п. Полное имя переменной так же не должно быть началом имени другой переменной. Например:
@vars { * d - неверное имя переменной, так как с нее начинается имя * другой переменной - dmin. Используйте другое, например d1 d = 0 dmin = 100 }

В таких случаях будет выведено сообщение об ошибке, а сценарий не будет выполняться пока вы не измените имя переменной.

Инициализация любых глобальных переменных в блоке @var и наличие пробелов слева и справа от знака "=" обязательно иначе будет выведено сообщение об ошибке:
@vars { ship = "" color = 100:0:255 gps = "GPS:Base:-62664.81:-80178.37:-27915.08:#" * вызовет ошибку из-за отсутствия пробела между знаком = и 0 distance =0 }

Обращаться к переменным можно по имени внутри любого @-блока указав перед ним "\" (обратную косую черту). При установке нового значения можно использовать сокращенную или полную форму записи Value of:
@test { \ship = Grid Name of MyShip Value of color = "0:0:200" FontColor of LCD Info = \color Write to LCD Info = "Корабль: \ship" WriteLine to LCD Info = "База: \gps" }

Для инициализации в блоке @var можно использовать любые значения, в том числе пустые, с указанием справа от знака "=" (равенства), пустой строки "", а так же состояния любых блоков, условные Cond() или математические Math() выражения, но не ссылки на другие переменные
@vars { x = 5 * это неправильная инициализация y = math(Position of MyPiston + \x) }

Использование двойных кавычек при инициализации или установке значений переменных отличных от числовых или логических True/False, не обязательно, кроме оговоренных случаев, но желательно, если вы хотите быть уверенным, что Easy Play воспримет значение так, как вы его задали. К тому же это будет смотреться более наглядно в блоке CustomData и просто облегчит отладку.

Локальные (динамические) переменные
Инициализируются при вызове сценария через поле "Аргумент" ПБ Easy Play. Например @-блок, позволяющий увидеть все доступные свойства и действия игрового блока, вызывается набором в панели управления в поле "Аргумент" вызова info(Airvent, Справка) и последующего нажатия "Выполнить". Здесь через "," (запятую) инициализируются две переменных с именами 1 и 2

Обращение к локальным переменным внутри @-блока так же как и в случае с глобальными переменными, осуществляется с помощью "\" указанного перед именем. В качестве имени переменной служит ее позиция при вызове:
@info { * вывод заголовка "Справка", указанного во второй переменной, в область Echo Echo = "\2\N" * вывести на консоль свойства и действия блока с именем Airvent, указанного в первой переменной Show \1 }
Такие переменные доступны только в том блоке, для которого они иницализированы. Любой сценарий, если потребуется, может быть вызван с разным количеством и значением переменных и их имена будут совпадать, но не будут перекрываться.

Hint: если надо узнать был ли передан аргумент или нет, используйте следующий код:
if \1 ? \ { Echo = "Вызов без аргумента" }

Использование переменных
В основном переменные используются для хранения состояний блоков и установки этих состояний. Все дело в том, что в одной строке нельзя установить значение одного свойства блока на основании другого. Например, если GPS-координата хранится в CustomData камеры, то нельзя прямо использовать это:
* так не правильно Fly to Data of Camera Lidar at 30 UpperLimit of Piston 1 = UpperLimit of Piston 2 * надо так \x = Data of Camera Lidar Fly to \x at 30 \x = UpperLimit of Piston 2 UpperLimit of Piston 1 = \x
Такое представление унаследовано от Easy Automatition и помогает упорядочить код.
Значения перменных
Присвоение значения переменной в Easy Play отличается от принятого в обычном программировании. В любой момент времени в переменной храниться не вычисленное на момент инициализации значение, а его представление, которое будет вычислено только в момент обращения:
@variables { * у переменной нет значения позиции поршня на момент инициализации pos = Position of MyPiston } @test { * обращение к переменной выведет текущую позицию поршня, например 1.5 Echo = "Позиция поршня: \pos" }

Такой подход обеспечивает возможность гибкого управления состоянием отдельных блоков, но бывает накладным для групповых операций, например, при инвентаризации всего корабля. В этом случае полезно знать последнее вычисленное значение, чтобы при каждом обращении к представлению переменной не проводить повторную инвентаризацию.
@vars { x = 0 * количество льда в инвентаре О2/Н2 генераторов iceg = math(int(InvX Ice of O2\H2 Generator / 1000)) } @ice * фиксируем в переменной x количество льда в О2/Н2 генераторах \x = \iceg if Value of x > 0 { if StatusX of Oxygen Tank on MyGrid < 50 { OnOff_On O2\H2 Generator } } else { OnOff_Off O2\H2 Generator } Echo = "Осталось \x тонн льда"
Если вместо x, анализировать по If и выводить по Echo значение переменной iceg, то EasyPlay дважды обратился к ее представлению и выполнит инвентаризацию, но фиксация значения через другую перемененную, позволит сделать это только один раз.

Фиксация значение свойств
Начиная с версии 1.32 EasyPlay позволяет фиксировать значение свойств блоков в переменных без использования дополнительной переменной. Этот способ называется трансляцией и используется также командами Write и Data
@vars { pos = Position of MyPiston fix = "{Position of MyPiston}" } @test { Extend MyPiston Delay 1000 * выведет текущую позицию поршня = 1.01 Echo = \pos * выведет стартовую позицию поршня = 0 Echo = \fix
Такая фиксация применима к любым свойствам блоков но не к вычисляемым значениям по math() или cond(), как показано в примере со льдом.

Конкатенация строк
Трансляцию можно использовать если требуется создать строку, состоящую из выборки токенов или значений нескольких свойств, чтобы затем проанализировать или использовать ее.
* эта команда поместит расширенные координаты объекта в Custom Data камеры Scan of Camera at 15000 * конкатенация токенов для формирования координат в формате GPS для автопилота \gps = "GPS:{Token[3] of Camera}:{Token[8] of Camera}:{Token[9] of Camera}:{Token[10] of Camera}:#" * устанавливаем точку назначения для автопилота Fly to \gps at 100
Трюк с альтернативой cond() при анализе свойств:
\x = cond(OnOff of AirVent = False & OnOff of Door = False : 0 : 1) if \x = 0 { Write to LCD = "Проход закрыт" } * так короче и быстрее с точки зрения выполнения сценария \x = "{OnOff of AirVent} {OnOff of Door}" if \x !? True { Write to LCD = "Проход закрыт" }

Псевдомассивы
В версии 1.32 появилась возможность трансляции составных имен переменных, которая позволяет создать нечто похожее на массивы значений переменных. Это достигается путем использования команды Value в правой части операции присвоения значения переменной.

Представленный ниже код выведет в область эха значения трех переменных arr1, arr2 и arr3: Blue, Green и Red соответственно:
@vars { arr1 = "Blue" arr2 = "Green" arr3 = "Yellow" x = 0 y = 0 } * обход псевдомассива из 3-х значений @arr { \y = math(\y + 1) if \y < 4 { * составное имя переменной \x = "arr\y" * трансляция полученного значения \x = Value of x Echo = \x @arr } }
Сокращения и регистр
Easy Play поддерживает сокращения при обращении к свойствам или действиям если такое сокращение можно однозначно трактовать. Например, чтобы отключить гасители корабля, нужно выполнить действие "DampenersOverride" для любого контроллера грида. Это слишком сложно запомнить, поэтому обращение можно сократить до "damp", поскольку никаких других действий, связанных с контроллером и начинающихся с этих четырех букв нет.

В случае с вентиляцией такое сокращенное обращение к действию, связанному с включением разгерметизации, не пройдет. Если вы посмотрите на список действий блока Airvent, то увидите там три почти одинаковых названия:

Depressurize — переключает разгерметизацию из одного положения в другое
Depressurize_On — включает разгерметизацию
Depressurize_Off — выключает разгерметизацию

Так что если обратиться к действию сокращенно, например "depress Airvent", то вместо включения вы переключите ее состояние из одного в другое, что может совпасть в моменте с вашими намерениями, а может и не совпасть. Поэтому для включения разгерметизации нужно использовать полную запись "Depressurize_On Airvent".

Регистр текста, т.е. какими именно буквами — большими или маленькими написана команда, так же не имеет значения. Такой способ называется регистронезависимым и если отдельно не оговорено, то все что вы пишите в своих @-блоках можно оформлять с учетом этого правила.

Для удобства некоторые системные команды так же имеют сокращения:

\var_name вместо Value of var_name — обращение к переменной внутри @-блока
Echo вместо Write to Echo — вывод информации в область Echo
Console вместо Write to Console — вывод информации на консоль

Сокращение значений переменных
При сравнении и установке значений переменных допускается использование префиксов сокращений "k" — кило и "m" — мега, умножающие предшествующее им числовое значение на 1000 и 100000 соответственно.
\thrust = 10.5 kN \power = 1.3 MW \volume = "1.5 kL" Echo = "Тяга: \thrust \N Мощность: \power \N Объем: \volume" if MaxImpulseAxis of Piston Escape > 100 kN { Echo = "Превышен макс. импульс по оси поршня" }
Этот сценарий выведет в область Echo следующее:
Чтобы избежать трансляции нужно заключить присваемое значение в двойные кавычки.
Выборка блоков и гриды
Любое действие или установка значения свойства связаны с выборкой одного или нескольких блоков по имени, которое включает указанные символы.

Например, если на корабле есть два десятка гироскопов, с именами Gyroscope 1, Gyroscope 2 ... Gyroscope 10, Gyroscope 11 ... Gyroscope 20, то действие "Override Gyroscope" переключит перехват управления для всех гироскопов, а действие "Override Gyroscope 1", только для 10-и: Gyroscope 1, Gyroscope 10, ... Gyroscope 19.

Выборка зависит от написания имени блока, т.е. действие "Override gyroscope" не вызовет перехвата управления ни одним гироскопом, т.к. их имена начинаются с большой буквы "G".

Выборку можно уточнить, указав перед началом имени специальный символ:

# — имя блока начинается точно с указанной последовательности, например "Override #Gyro" вызовет перехват управления всеми гироскопами, если их имя начинается с Gyro.

! — имя блока в точно соответствует указанному, например "Override !Gyroscope 1" перехват будет выполнен только для одного гироскопа с именем Gyroscope 1

? — имя блока содержит целые слова, начинающиеся с указанных слов вне зависимости от их написания. Например, "Override ?gyro turn" вызовет перехват управления всеми гироскопами в имени которых есть слова, начинающиеся на "gyro" и "turn", таких как Gyroscope 01 Retro Turn, Gyro Turn Left и т.п.

В качестве имени блока можно так же использовать переменную, это позволит избежать опечаток в имени блока в коде сценария и проще организовать настройку:
@var { camera = Camera Lidar } @test { Data of \camera = "" }

При формировании имен блоков, которые будут участвовать в автоматизации, желательно учитывать способы обращения к ним по именам, чтобы лишние блоки не попадали в выборку.
Если в выборку попадут блоки, которые не относятся к заданному действию, то скорее всего
ничего не произойдет. Большинство свойств и действий уникальны для разных типов блоков,
однако кнопка вкл./выкл. (действие OnOff) есть почти у всех блоков. Поэтому при выключении батарей "OnOff_Off Battery" можно случайно отключить и дверь, ведущую в аккумуляторный отсек, если в ее названии встречается "Battery", типа Door in Battery Bay.

Выборка группы блоков
Чтобы быть уверенным наверняка, что в выборку попадают нужные вам блоки, можно через панель управления объединить их в группу и использовать ее имя для установки свойства или выполнения действия. Имя группы в этом случае всегда указывается точно и ограничивается круглыми скобками:
Override (Gyroscopes)
В именах групп лучше также не использовать разделители типа ",*-+/(){}" это может ограничить использование групп например в качестве локальных переменных при вызове @-блока с параметрами, указанными через "," или при выводе состояния блоков списком в команде Status.

Выборка с учетом грида
Грид или сетка, это совокупность блоков, статически соединенных друг с другом. Сабгрид или подсетка, эта совокупность блоков, соединенных с другим гридом через динамические блоки — поршни, шарниры, роторы. В Easy Play различаются три типа гридов:

MyGrid (основной грид) — блоки, находящиеся на гриде, в котором установлен ПБ Easy Play

AllGrid — MyGrid и все сабгриды, соединенные с основным через динамические блоки — роторы, шарниры, поршни

MyShip — AllGrid и все что пристыковано к нему через коннекторы

Имя_Грида — точное указание имени грида с учетом написания. Может применяться для управления пристыкованными через коннектор кораблями. Например, "Unlock Connector on SE Escape Pod" отсоединит все коннекторы шатла с именем "SE Escape Pod"

Уточнение грида производится с использованием ключевого слова on. Например
Over of Ion Thruster Forward on MyGrid = 50% IncreaseOverride Ion Thruster Forward on MyGrid
Такое уточнение позволит исключить перехват управления трастеров других кораблей, пристыкованных к вашем через коннекторы. Если грид не указан, то как и в Easy Automatition, выборка производится для всех доступных блоков, т.е. для MyShip.

Замечание: гриды, присоединенные через активный блок-соединитель считаются частью того грида, к которому они присоединены.
If/Else. Простая логика
Использование логических выражений If/Else полностью унаследовано от Easy Automatition 2.0 и позволяет использовать простую бинарную логику с использованием традиционных операций сравнения: = равно, != не равно, < меньше, > больше. В Easy Play к ним еще добавлены операции: ? — входит в строку и !? — не входит в строку, применяемые для анализа строчных данных.

Логические блоки последовательности действий разделяются традиционно фигурными скобками "{}", но в отличии от оригинала их не нужно теперь указывать с новой строки. Типичное логическое выражение выглядит так:
\x = Angle of MyRotor IF Position Of MyPiston on MyGrid > \x { ... } Else If Value OF x = 90.0 { ... } else { ... }
Обратите внимание на регистр написания ключевых слов If / Else / Of / On их можно оформлять в любом виде, но вот последовательность операндов сравнения всегда идет слева направо. Т.е. сначала указывается свойство или переменная, значение которой анализируется, затем одна из логических операций, и в конце значение, с которым нужно сравнить. Перестановка операндов не допускается.
* это неверное оформление, хотя условие тоже самое IF \x < Position Of MyPiston on MyGrid { ... * тоже неверно, так как второй операнд включает обращение к переменной в полной форме } else if Position Of MyPiston on MyGrid < Value of x { ... }
Теперь обратите внимание на сравнение значения переменной "x" первом и втором условии if.

Во-первых, если переменная используется в первом операнде, то обращаться к ней можно как в полной "Value of x", так и в сокращенной "\x" форме. Если переменная используется во втором операнде, то обращаться к ней можно только в короткой форме "\x".

Во-вторых, точность вычисления при сравнении задается вторым операндом, поэтому в выражении указан угол поворота ротора не просто 90, а 90.0 Это означает, что под условия равенства подойдут все значения угла поворота, математическое округление которых до первой десятичной точки даст 90.0, т.е. углы 90.01235, 90.0439, значение 89.786 к таковым не относится, поскольку результат округления будет равен 89.8.

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

Новые операции вхождения: ? и !? позволяет определить содержится или нет указанное значение в анализируемом тексте. Сравнение производится без учета регистра. Например:
if Data of Camera Lidar ? "GPS:" { \coord = Data of Camera Lidar Fly to \coord at 30 Fly Start }
Это пример межскриптовой коммуникации с другим моим скриптом Raycast Lidar, который в случае наличия цели по лучу лидара помещает данные границы объекта в CustomData камеры, которая используется в качестве лидара. После чего их можно считать и использовать в качестве точки назначения для автопилота.

Здесь условное выражение как раз проверяет наличие вхождения "GPS:" в поле CustomData блока с именем "Camera Lidar" и в случае нахождения ее помещает координаты GPS в автопилот через переменную "coord" и активирует его.

Замечание: для сравнения с пустой строкой используется "=", а в качестве второго операнда "" (две двойные кавычки)

Вычисление логических выражений
Логические выражения бывают простыми, когда используются одиночные операторы сравнения типа "=", "!=", "<", ">" или "?" и сложными, когда используются удвоенные операторы сравнения типа "==", "<<", ">>" или "??".

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

Например, если вы хотите узнать есть ли открытые двери, то логическое выражение
if Open of Door = True { ... }
будет истинным если открыта хотя бы одна дверь. Если вы хотите проверить, все ли двери на корабле закрыты, то нужно использовать удвоенный оператор сравнения:
if Open of Door on MyGrid == False { ... }
Напомню, что по умолчанию выборка блоков распространяется на все гриды, в том числе и на присоединенные через коннекторы. Так что если ваш корабль пристыкован к станции, на которой так же есть двери, имена блоков которых содержат "Door", то чтобы не затронуть и их тоже, при запросе нужно уточнять грид для которого выполняется поиск блоков.

Переменные в именах блоков
При анализе свойств блоков иногда возникает необходимость в проверить значение блока, имя которого формируется с учетом значения переменной. Это бывает удобным при настройке сценария. Например:
@var { controller = "Cockpit" x = 0 } @damp_off { \x = Damp of \controller * это будет работать if \x = False { Damp of \controller = True } * а это - нет if Damp of \controller = False { Damp of \controller = True }
Cond. Составная логика
Новый оператор Cond позволяет вычислять сложные не бинарные логические выражения с применением логики "и/или". В основном он был введен для того, чтобы сократить в @-блоке количество бинарной логики if/else. Например, если вы хотите вывести на экран статус ворот открывающихся поршнем, то нужно будет написать что-то типа
if Position of Piston Escape = 0 { Write to LCD Info = "Ворота закрыты" } else { Write to LCD Info = "Ворота открыты" }
Подобных условий может быть много, что увеличивает размер кода сценария. Вместо написания этих 5 строк можно обойтись всего парой если использовать переменную:
\x = cond(Position of Piston Escape = 0 : закрыты : открыты) Write to LCD Info = "Ворота \х"

Как видно из примера, синтаксис Cond() прост: сначала идет условие, затем разделитель":" (двоеточие), затем значение, которое нужно присвоить при совпадении условия, затем снова ":" и последним идет значение, которое нужно присвоить, если условие не совпадает.
Если значение, которое нужно установить, или переменная, которую нужно проверить, содержит двоеточие ":", то для правильной трансляции нужно использовать двойные кавычки, например: cond("\color" ? 250 : "0:0:240" :"250:0:0")

Теперь рассмотрим случай, когда ворота открываются поршнем, который стоит на роторе и ворота будут считаться открытыми только тогда, когда поршень выдвинут на 7 м, а ротор развернут на 180 градусов. В простой логике придется написать вложенный if:
if Position of Piston Escape = 7 { if Angle of Rotor Escape = 180 { Write to LCD Info = "Ворота открыты" } else { Write to LCD Info = "Ворота закрыты" } } else { Write to LCD Info = "Ворота закрыты" }
С применением cond() все будет выглядеть гораздо компактнее:
\x = cond(Position of Piston Escape = 7 & Angle of Rotor Escape = 180 : открыты : закрыты) Write to LCD Info = "Ворота \х"

Как видно из примера, Cond(), подобно math() из Easy Automatition, допускает многострочную запись, что удобно если условий больше одного. При таком оформлении желательно, чтобы каждая новая строка не начиналась с символа-разделителя — в примере это "&" и ":".

Для логики "или" используется одиночный разделитель "|" с помощью которого задачу определения положения ворот можно было бы решить так:
\x = cond(Position of Piston Escape < 7 | Angle of Rotor Escape != 180 : закрыты : открыты) Write to LCD Info = "Ворота \х"

Все переменные, используемые в синтаксисе Cond, должны указывать в краткой форме с применением "\" (обратного слэша):
\x = 50 \speed = Speed of MyShip \x = cond(\speed = 0 : Stoped : \x) Echo = Скорость: \x
Условные циклы или замыкания
Как и Easy Automatition, Easy Play не имеет специальных операторов циклов, потому что их можно реализовать теми средствами, которые есть в языковых конструкциях скрипта. Для того, чтобы организовать цикл достаточно условного оператора if и вызова по ссылке самого себя.

В свое время при создании реплики APC-M577 из фильма "Чужие 2", я использовал это, чтобы плавно изменять высоту подвески бронетранспортера, чтобы он не подпрыгивал при резкой установке ее в крайнее верхнее положение -50 см.
@wheel_up { * уменьшить высоту подвески группы колес DecreaseHeight (APC, Wheels) * если высота переднего левого колеса больше -49 см if Height of Wheel 5x5 FL > -0.49 { * выполнить задержку в 1/4 сек Delay 250 * продолжить уменьшать высоту вызовом самого себя @wheel_up } }
За одно выполнение команды "DecreaseHeight" APC-M577 поднимался на 11 см. Т.о. для подъема в крайнее верхнее положение с 0, цикл выполнялся 5 раз после чего сценарий завершал работу по условию. Поэтому такой цикл и называется условным. В традиционном программировании подобный цикл называется While.

Возможность Easy Play изменять представление глобальных переменных внутри @-блока позволяет организовать и итерационный цикл For, связанный с достижением переменной граничного значения. Вот как это можно сделать на примере сценария 10-и секундного обратного отсчета:
@vars { x = 10 } @countdown { if Value of x > 0 { Write to LCD Alert = "Обратный отсчет: \x" * уменьшим значение глобальной переменной на 1 с помощью math() \x = math(\x - 1) * ждем 1 сек Delay 1000 * и вызываем сами себя @countdown } Write to LCD Alert = "Эвакуация!" * вернем значение переменной для возможного повторного использования сценария \x = 10 }
Прервать выполнение подобного замыкания можно вызовом ПБ Easy Play с параметром reset

Замечание: вложенные условные циклы могут привести к неправильной работе или краху
Delay/When. Задержка выполнения
Easy Play имеет два оператора, которые на время приостанавливают выполнение скрипта.
Это связано в первую очередь с использованием динамических блоков — поршней, роторов,
шарниров, створок герметичных ворот, дверей, словом со всеми блоками для которых переход из одного состояния в другое требует времени.

Delay. Приостановка на заданное время
Delay позволяет приостановить работу скрипта с точностью до 1 милисекунды. 1 сек
соответствует 1000 мс, поэтому чтобы задержать выполнение на нужное количество секунд,
нужно просто умножить их количество на 1000.
Delay 3000 Write to LCD Info = "Прошло 3 сек."
По прошествии указанного времени Delay передаст управление следующей за ним команде. Если включен режим отладки, то время задержки будет выводится в область Echo скрипта.

Hint: Используйте Delay(100) для задержки после стыковки корабля, если автоматизация требует последующего анализа состояния блоков присоединенного через коннектор грида.

When. Ожидание наступления события
When, как и If является простым бинарным логическим оператором и обладает теми же возможностями и синтаксисом, но в отличии от него он приостанавливает действия скрипта до наступления определенного условным выражением события. После того, как событие наступило, происходит передача управления следующей за When команде сценария, "{}" не требуются.
* запуск движения поршня к отметке 7 м со скоростью 1 Move MyPiston to 7 at 1 * ожидание достижения отметки When Position of MyPiston = 7 * вывод на LCD о завершении события Write to LCD Info = "Ворота открыты"
Все просто и очевидно, за исключением одного момента — в реальной игре событие может
просто не наступить, например из-за деформации брони, которое помешает поршню достичь
нужной отметке и скрипт просто зависнет.
Поделать с этим ничего нельзя, но можно выполнить команду Reset, чтобы ПБ вышел из цикла
В остальном оператор When очень удобен и если неизвестно примерное время наступления события, то он позволяет дождаться этого момента с точностью до 1 тика таймера.

Используйте When с учетом того, в каких условиях динамический блок будет работать и если нет полной уверенности, что все пойдет как надо, то лучше использовать оператор задержки Delay, который так же задерживает выполнение скрипта, но на точно указанное вами время.

Если включен режим отладки, то время задержки будет выводится в область Echo скрипта. Если нет, его можно получить командой Sync of Script, если использовать ее сразу после When.

Это может быть полезно для тех, кто предпочитает автоматизацию на таймерах, т.к. с
помощью When можно с точностью до милисекунды узнать время, за которое событие происходит. Например, узнать за какое время в игре полностью открываются створки герметичных ворот.
Math. Математика
Как и оригинальный скрипт, Easy Play может использовать многострочные математические
выражения при инициализации переменных или в качестве правого операнда логических
выражений. Поддерживаются следующие математические операции:

+ (плюс) — сложение
- (дефис) — вычитание
* (звездочка) — умножение
/ (косая черта) — деление

Приоритет вычисления операция задается вручную при помощи "()" круглых скобок. Например, для правильного вычисления выражения 3+4*5 = 23 нужно расставить круглые скобки так: 3+(4*5), чтобы получить 23. Использование в качестве операндов значений свойств блоков осталось неизменным:
@vars { level = math( (Position of Piston/2.5) + (abs(Angle of Rotor*0.5) - 1) }
В примере показано многострочное оформление математического выражения и приоритет, заданный при помощи "()". Во избежании ошибок вычисления при записи выражения в несколько строк не следует начинать новую строку с символа операции.

Дополнительно к математическим операциям реализованы функции:

abs() — абсолютное значение
int() — округление до целого числа

Извлечение числового значения
Команда math() умеет извлекать из операндов, представленных переменными или свойствами блоков, первое по счету числовое значение с десятичной точкой, а так же вычислять выражения в строчном представлении. Например:
* установит х = 100 от значения давления в 100% \x = math(Info[3] of Airvent) * установит x = -31.789 - первое по счету число в GPS-координатах \x = math("GPS:База:-31.789:67.978:29.17965") * поместит в х информацию от Build Progress проектора, например "4/20" \x = Info[4] of Projector * вычислит х = 0.2 от строчного представления деления 4/20 \x = math(\x)
Замечание: в последнем случае трансляция строчного представления математического выражения должна осуществляться через переменную, как показано в примере. Попытка прямого вычисления через свойства блока math(Info[4] of Projector) вызовет 419 ошибку.
Token. Текст с разделителем
Для анализа текстовых данных и организации вывода часто требуется извлечь часть текста с применением разделителя. Такие части принято называть "токенами". Например, что того чтобы вывести тип отсканированного по лидару объекта, вам потребуется второй токен из полного формата GPS координат, который команда Scan помещает в поле "Свои данные" камеры.

Синтаксис команды Token похож на синтаксис полного обращения к переменной Value, где имя переменной указывается без лидирующей "\": Token[N] of var. В квадратных скобках "[]" указывается порядковый номер токена. Отсчет начинается с 1.

Если значение в [] превышает допустимое или неверное, то возвращается 1-й токен. Без [] возвращается количество токенов.

Начиная с версии 1.32 в [] скобках можно указывать имя токена, чтобы получить его индекс в строке. Если токена в строке нет, то возвращается 0. Если строка токенов включает числа, а требуется получить его индекс, то значение в [] следует заключить в двойные кавычки:
\jump = "5:6:7:8:9:10" * x = 1, а без кавычек x = 9 \x = Token["5"] of jump

Извлечение токена
Извлечение и установка токена всегда производится только для переменной:
* scan помещает в поле "Свои данные" камеры GPS:Asteroid:x:y:z Scan of Camera Lidar at 10000 * считываем данные в переменную lidar \lidar = Data of Camera Lidar * извлекаем второй токен по разделителю "двоеточие" = Asteroid Echo = "{Token[2] of lidar}" * подсчет количества токенов в тексте = 5 Echo = "{Token of lidar}" * это неверно, извлечение возможно только из переменной Echo = "{Token of Data of Camera Lidar}"

Построчное извлечение выполняется командой TokenLine. В тексте должны присутствовать переносы строки или символ новой строки \N, чтобы применить эту команду
@var { menu = "Ship status Drone status Exit from menu" } @test { * извлечет вторую строку = Drone status Echo = "{TokenLine[2] of menu}" }

Изменение токена
Если значение в "[]" превышает допустимое, неверно или команда используется без "[]", то устанавливается 1-й токен:
@var { color = "0:0:0" menu = "Ship status Drone status Exit from menu" } @test { * установит переменную color = 255:0:0 - красный цвет Token[1] of color = 255 * заменит вторую строку переменной menu на "View drone" TokenLine[2] of menu = "View drone" }
Status. Состояние блока
Основой практически любой автоматизации является анализ текущего состояния того или
иного игрового блока, которые можно устанавливать через панель управления и о которых рассказано в разделе "Свойства и действия". Однако игровой движок использует больше свойств, чем те, что доступны через панель управления. Для доступа к ним используются две команды — Status и Info.

Status. Текущее состояние блока
Для разных блоков существую различные промежуточные состояния, в которых они могут
находиться — батарея может заряжаться, створки ангара — закрываться, турель — стрелять, а коннектор быть готовым к стыковке.

Ниже представлен список состояний для различных типов блоков, которые доступны по команде Status of Blocks on Grid, где Blocks — выборка блоков, а Grid — необязательное уточнение грида MyGrid или AllGrid (по умолчанию MyShip).

Ассемблер
Idle, Producing, Stopped — если нет слитков для производства, в ()
режим работы: Assembly, Disassembly
Бак (О2/Н2)
чдт = процент заполнения бака, в () режим накопителя: StockOn, StockOff
Батареи
чдт = процент заряда, в () состояние зарядки: Auto, Recharge, Discharge
Вентиляция
Depressurized, Depressurizing, Pressurized, Pressurizing
Ветрогенератор
чдт = текущая отдача в Вт, в () процент от максимальной отдачи
Двери, ворота, створки ангара
Opening, Open, Closing, Closed
Коннектор
Unconnected, Connectable, Connected, в () имя припаркованного корабля
Курсовое оружие (пулеметы, ракетницы)
Idle, Ready, в () остаток боезапаса
Лазерная антенна
Idle, RotatingToTarget, SearchingTargetForAntenna, Connecting, Connected, OutOfRange
Очиститель
Idle, Producing
Прыжковый двигатель
чдт = дальность прыжка в км, в () текущее состояние: Charging, Ready, Jumping)
Проектор
строка с разделителем ":" из 8-и токенов:
1=наличие чертежа в проекторе, True/False
2=общее число блоков в чертеже
3=общее число функциональных блоков в чертеже
4=число блоков, которые можно сварить
5=недостающие функциональные блоки
6=недостающие конвееры
7=недостающие блоки брони
8=общий % недостающих блоков (повреждения), чдт
Поршень
Extending, Extended, Retracting, Retracted, Stopped — если скорость установлена в 0
Ротор и шарнир
Attached, Detached
Сенсор
Idle или имя игрока/грида дружественных фракций
Солнечная панель
чдт = текущая отдача в Вт, в () процент от максимальной отдачи
Соединитель
Idle, Merged
Сортировщик
Whitelist, Blacklist — режим, а не список фильтра
Таймер
Countdown — если ведется отсчет
Турели автоматические
Idle, Target — видит цель, Aimed — нацелена, в () остаток боезапаса и % повреждения
Шасси и магнитные пластины
Unlocked, ReadyToLock, Locked

Команда Status возвращает состояние первого найденного блока из выборки. Для других типов блоков возвращается Active, если блок работоспособен. Если блок выключен через панель управления выводится Offline, если поврежден выше предела разрушения — Damage.

Все указанные в правом столбце таблицы значения, за небольшим исключением, — внутри игровые, поэтому при анализе их нужно указывать полностью и с учетом написания:
If Status of MyConnector = Connectable { Lock MyConnector }
Замечание: если дополнительная информация, выводимая в "()" круглых скобках, не нужна, то используйте StatusX вместо Status. StatusX для проектора вернет % повреждений.

Status. Вывод состояния выборки блоков
Несколько иной синтаксис команды, позволяет получить список состояния всех блоков выборки: Status Blocks of Grid, где где Blocks — выборка блоков, а Grid — обязательное уточнение грида MyShip, MyGrid или AllGrid.

После выполнения такой команды будет сформирован построчный список состояний всех блоков, который можно вывести на LCD-панель. Например следующий сценарий:
@ship_status { Write to LCD Status = "< Connector Status>\N {Status Connector of MyGrid}\N <Assembler Status>\N {Status Assembler of MyGrid}" }
Выведет на панель с именем "LCD Status" состояние всех коннекторов и сборщиков
Это удобнее, чем последовательное перечисление всех сборщиков и коннекторов корабля, для отображения их состояния командой Status.

Замечание: если дополнительная информация, выводимая в "()" круглых скобках, не нужна, то используйте StatusX вместо Status.

Status[Active]. Активность блоков
Для просмотра сколько блоков из выборки активно используется команда Status[Active]:
* выведет 1/3 если один из трех реакторов группы (Reactors) активен Echo = "{Status[Active] (Reactors) of MyShip}"
Hint: полученное значение можно использовать через переменную для трансляции math(). Допустимо сокращение до StatusA

Status[Middle]. Среднее значение
Для блоков, состояние которых возвращается числом с "." десятичной точкой с помощью Status[Middle] можно получить среднее значение:
* если кислорода с учетом всех баков менее 75% if Status[Middle] Oxygen Tank of MyShip < 75 { * если в О2/Н2 Генераторах есть лед if InvX of O2/H2 Generator > 0 { * включить все генераторы OnOff_On O2/H2 Generator } }
Замечание: для блоков другого типа возвращается 0. Допустимо сокращение до StatusM

Status[Total]. Суммарное значение
Применима для блоков, состояние которых возвращается числом с "." десятичной точкой с помощью:
* если уровень отдачи менее 100 Вт if Status[Total] Solar Panel of MyShip < 100 { * запускаем генератор OnOff_On Gydrogen Generator }
Замечание: для блоков другого типа возвращается 0. Допустимо сокращение до StatusT
Info. Информация о блоке
Вы можете видеть ее в области Echo при выборе блока в списке в панели управления. Info позволяет получить построчный или поименный доступ к этой информации, если это имя можно выделить и вернуть соответствующее ему значение.
.
Синтаксис команды: Info[Val] of Blocks on Grid, где Blocks — выборка блоков, Val — номер строки, или имя свойства в квадратных скобках, а Grid — необязательное уточнение грида MyGrid или AllGrid (по умолчанию MyShip).

Если [] нет, или в них указан номер несуществующей строки или свойства, то будет возвращен весь блок дополнительной информации.

Блок дополнительной информации в выводе команды Show на LCD располагается выше "Свойства" и ниже названия корабля. Блок может быть пустым, а его содержимое зависит от языка, который установлен в Space Engineers (не в локализации Easy Play). В данном случае это русский язык.

Построчный доступ к свойству осуществляется путем указания номера строки из которого нужно взять значение, а именной — имени свойства которое указано в строке до ":" (двоеточия)
\x = Info[3] of Airvent 1 \y = Info[Давление] of Airvent 1 * в обеих случаях будет выведено 100.00% Echo = "Значение в 3-й строке: \x & \y" if Value of x ? "100.00" { Write to LCD Info = "Помещение герметично" }
Первый способ обращения не зависит от установленного в игре языка, а второй — зависит, т.к. свойство будет называться у всех по разному. Если вы планируете выкладывать крафт в Steam, то лучше использовать первый способ.

Анализ значения чаще всего лучше выполнять с помощью оператора вхождения в строку "?", но если свойство блока представлено числом, без дополнительных символов справа, то можно использовать и другие логические операторы.

После выхода Automotons Update появились блоки "искусственного интеллекта", которые имеют динамическую и не уникальную информацию о блоке. Например блок AI Offensive имеет две строки Status и для получения последнего значения этого свойства следует указать перед ним восклицательный знак "!" — !Status
Rename. Переименование блоков
Эта команда позволяет переименовывать блоки в пакетном режиме, что позволяет достаточно быстро оптимизировать их названия для последующей автоматизации.

Синтаксис команды включает ключевой слово Rename, обычную выборку по имени, ключевое слово to и последовательность префиксов, формирующих новое имя. Вместо выборки блоков можно использовать так же все блоки грида и подсетки: MyGrid, AllGrid, а вот MyShip ссылается здесь на имя основного грида, который указывается в системной панели во вкладке "Инфо".

Префиксы для переименования
Алгоритм переименования полностью изменен относительно Easy Automatition и основан на использовании префиксов, начинающихся с символа "#" (решетка):

#n2 — автоинкримент, где 2 количество цифр (м.б любым числом), префикс используется для порядкового индексного переименования блоков
* все гироскопы будут с именами Gyro 001, Gyro 002 ... Gyro 999 Rename Gyroscope to Gyro #n3

#r3 — случайное число, где 3 количество цифр (м.б любым числом), этот префикс можно использовать для присвоения уникальных имен автоматически распечатываемых дронов, на которых установлен Easy Play. Для MyShip префиксы #* и #def не обрабатываются.
* в результате получится что-то типа Drone_607 Rename MyShip to Drone_#r3

#def — ссылка на оригинальное внутри игровое имя, которое вы можете увидеть при выводе свойств и действий на консоли и в области Echo по команде Show.
.
Этот префикс используется для переименования всего крафта с языков, отличных от английского. Он особенно удобен для переименования иероглифических имен блоков. Просто попробуйте выполнить этот сценарий для вот такого крафта и посмотрите, что получится.
@grid_rename { Rename MyGrid to #def }

#* (звездочка) — ссылка на текущее имя, из которого с помощью "-" (минус) можно убрать лишнее вхождения

Типичной задачей переименования является добавление или замена префикса перед именем блока на всем гриде. С помощью EasyPlay это можно легко сделать:
Rename MyGrid to New #*-Old
Здесь Old — старый префикс который нужно заменить, а New — новый префикс. Если, к примеру ваши блоки начинались с префикса My: My Gyroscope, My Battery..., а вы хотите чтобы они назывались Me Gyroscope, Me Battery... то вместо Old нужно указать My, а вместо NewMe. Если у блока нет префикса Old, то префикс New, то префикс New будет добавлен к имени блока.

Для того чтобы не переименовывать блоки сразу, можно предварительно посмотреть результат, ограничив всю последовательность префиксов символами "~". После выполнения такой команды "Rename" изменения имен блоков не произойдет, а результат будет выведен в область Echo. Если результат группировки префиксов вас устраивает, просто уберите символы "~" и повторно запустите сценарий.

Переименование из панели управления
С помощью локальных переменных легко написать @-блок, который будет выполняться из строки "Аргумент" ПБ Easy Play
@rename { Rename \1 to \2 }
Запуск сценария с параметрами типа rename(Gyro, #* #n1) добавит к имени всех блоков, имя которых начинается с "Gyro" порядковый номер начинающийся с "1".

Этот @-блок из 3-х строк позволит выполнять любые переименования прямо из панели управления. Для наглядности можно использовать фильтр по имени в панели управления, который расположено выше списка блоков.

Замечание: с "-" (дефис) в оригинальном имени, конечно, есть проблемы, — если он в нем есть, то его нельзя удалить, но в остальном подобный алгоритм позволяет получать практически любые составные имена.
Run. Межскриптовая коммуникация
Любой сценарий Easy Play может запускать скрипты, расположенные в других программных блоках, с любым аргументом. Это позволяет организовать связь между различными скриптами и управлять ими в зависимости от условий. Например, можно переключать турель из ручного управления в автоматическое, передать координаты целей скриптам управления ракет и т.п.

Обращение к другому программному блоку осуществляется с помощью команды Run. Аргументы могут указываться через знак "=" как в Easy Automatition или в круглых скобках "()":
Run PBL Fire = 1 Run PBL Fire(2, decoy)
Выполнение с аргументом по умолчанию осуществляется либо внутриигровой командой RunWithDefaultArgument (сокращения не допускаются), либо короче - с аргументом "defarg":
RunWithDefaultArgument PBL Fire Run PBL Fire(defarg)
Команда Run выполняется для первого найденного на корабле программного блока имя которого в точности совпадает с указанным. Для того, чтобы выполнить команду для всех блоков с указным именем используйте команду RunAll с тем же синтаксисом. Применять уточняющие условия выборки, связанные с символами "!#?" не надо.

Замечание: командой "Run" нельзя запустить (замкнуть на себя) ПБ Easy Play.
Set. Настройка блоков по образцу
Команда Set позволяет устанавливать свойство одного блока или выборки блоков по типу другого блока. Это позволяет легко настраивать однотипные блоки, имеющие большое количество настроек, например, LCD панели, лампы, подвеску и т.п. без необходимости их группировки или выбора в панели управления.

Синтаксис команды: Set выборка_блоков on блок_образец, где выборка_блоков — выборка блоков по имени по всем доступным гридам, а блок_образец — точное имя блока с учетом написании, настройки которого будут использованы для установки значений свойств блоков выборки. Например:
Set #Light bridge on Light bridge 01
Установит все настройки ламп освещения, имена которых начинаются с "Light bridge" по типу лампы с именем "Light bridge 01". В последнем случае уточнение имени блока-образца с помощью префикса "!" происходит автоматически и в нем не нужно использовать никакие другие префиксы уточнения.

Следующий сценарий в одну строку позволит настраивать блоки по образу прямо из панели управления через аргумент ПБ Easy Play:
@set { Set \1 on \2 }
Замечание: настройка по образцу блоков, имеющих несколько экранов (поверхностей), производится командой Surface, описанной в разделе "Настройка вывода LCD".

Пакетная настройка блоков
Начиная с вер. 1.33 в качестве образца можно указывать не имя блока, а текстовые данные, где нужные вам значения свойств будут установлены пакетом в формате "Свойство = Значение" и перечислены команды, которые можно будет применить к нужному блоку:
\light = "OnOff_Off Color = 255:0:0 Radius = 10 Blink Interval = 1 OnOff_On" Set Light Bridge on "\light"
Последнее значение всегда должно быть заключено в "" двойные кавычки. Вместо новой строки можно использовать разделитель \N. Свойства необходимо указывать точно так, как они перечисляются в выдаче команды Show[property], а команды точно так как в выдаче Show[action]. Сокращения не допускаются.

Такая настройка называется пакетной. Она позволяет устанавливать свойства блоков из хранимых значений и использовать типовые настройки в разных крафтах. Я, например, всегда настраиваю освещение рубки одинаково и гораздо удобнее хранить настройки отдельно, чем загружать в мир похожий корабль, чтобы вспомнить, как настраивается освещение.

В пакете можно указывать только свойства и команды блоков из списка Show. Другие команды EasyPlay не обрабатываются, кроме команды AI (см. раздел "Другие свойства и команды")

Перепрошивка AI
Еще одним применением такой настройки является перепрограммирование поведения AI-блоков. Это позволяет прямо на ходу менять настройки поведения блоков AI Offensive и AI Defensive переписывая их установки в пакетном режиме, которые можно хранить в поле "Свои данные" любого игрового блока.
\behavior = "AI = CycleOrbit OffensiveCombatIntercept_OverrideCollisionAvoidance = True OffensiveCombatCircleOrbit_CircleDistance = 800 SetTargetPriority_Largest SetTargetingGroup_Weapons" Set AI Offensive on "\behavior"
Таким образом можно, например, "перепрошить" ракету или ударный дрон после его печати на принтере, изменив настройки, установленные в чертеже, изменив тем самым его поведение в зависимости от типа атакуемой цели.
Data. Поле "Свои данные"
Вы можете считывать и записывать информацию в поле "Свои данные" (CustomData) любого блока как целиком, так и с точностью до переменной, установленной в секции, если там используется оформление типа "имя_переменной = значение_переменной". В таком формате оформлены настройки многих популярных скриптов, например скриптов Whiplash141.

Обработка данных в поле CustomData производится с помощью линейки команд Data. Например, если поле "Свои данные" текстовой панели "LCD Info" содержит настройки:
[setup] Font = 1.3 Color = 0:0:25
то следующие команды:
* полностью очистит CustomData Data of LCD Info = "" * добавит к существующим данным 5, в итоге Color = 0:0:255 DataAdd of LCD Info = "5" * добавит к существующим данным новую строку DataLine of LCD Info = "BgColor = 255:0:0" * считает в переменную \y значение параметра Color (поиск зависит от регистра) \y = Data[Color] of LCD Code * установит значение переменной Color (установка зависит от регистра) Data[Color] of LCD Info = 100:100:100 * перепишет CustomData (многострочная запись с использованием двойных кавычек) Data of LCD Info = "[setup] Font = 1 Color = 255:0:0 BgColor = 255:255:255"

Если при установке значения параметра он не будет найден, то к CustomData будет добавлена новая строка с этим параметром и значением через разделитель "=" (равно).

Вы можете так же использовать разделитель ":" (двоеточие) вместо "=". В этом случае для доступа к значениям параметров следует вставить ":" перед его именем. Например, мой скрипт Raycast Lidar выводит данные сканирования в следующем формате:
Distance: 10703 m Type: Asteroid Size: 768 m ------------------------ * получения размера астероида \size = math(Data[:Size] of LCD Lidar)
Замечание: команда Data обрабатывает только первый блок из выборки, поэтому лучше полностью указывать имя блока, чтобы работать с CustomData конкретного блока.

Чтение @-блока
В отличии от Easy Automatition, Easy Play не умеет выполнять @-блок из CustomData другого игрового блока, но может считать его. Это свойство можно использовать, чтобы вынести часть информации за рамки кода своего ПБ, например для организации подсказок по управлению
@help { Write to Control Seat Hold = "{Data[@help_\1] of Control Seat Hold}" }
Этот однострочный сценарий используется на тестовом крафте и позволяет выводить на основной экран станции управления подсказки для управления с помощью цифровых панелей. Имя блока указывается также как для чтения переменной с лидирующим "@".

Вызов @-блока "help" осуществляется через выполнение ПБ Easy Play с аргументом "help(N)", где N — номер цифровой панели от 1 до 9, а CustomData контрольной станции содержит соответствующие @-блоки.
@help_1 { #1 - Hydrogen on/off #2 - Hydrogen Force on/off #3 - Ion on/off ... } @help_2 { #1 - Rescan Inventory #2 - Switch screen mode ... }
Дополнительные способы установки значений со ссылкой на свойства блоков см. в разделе "Write. Запись на LCD".
Write/Text. Запись и чтение LCD
Запись возможна на любой экран (поверхность) блока, если он есть, за исключением
модуля выживания и медицинского блока.

Запись производится линейкой команд Write. Номер экрана, на который выводятся данные, указывается вслед за командой в квадратных скобках "[]". Отсчет экранов начинается с нуля. Если номер не указан, то запись производится на нулевую поверхность.
* очистит экран панели Write to LCD Info = "" * выведет на центральный экран кокпита время корабля Write to Industrial Cockpit[1] = "{Time of MyShip}" * выведет на последний экран Sci-Fi 4-х кнопочной панели Write to Button Panel[3] = "Дверь закрыта" * добавит к существующим данным "Открыто" или "Закрыто" \x = cond(Open of MyDoor = True : Открыто : Закрыто) WriteAdd to LCD Info = \x * добавит к существующим данным новую строку WriteLine of LCD Info = "Коннектор {Status of MyConnector}" * многострочный вывод на экран Write to LCD Info = "Управление #1 - включить #2 - выключить"

Команды Write и Data могут включать в себя прямой вывод свойств блоков, которые должны быть заключены в фигурные скобки "{}", а правый операнд после знака "=" должен быть заключен в двойные кавычки.

При этом поддерживается построчный вывод свойств всей выборки блоков. Например, чтобы вывести на экран состояние всех коннекторов корабля, достаточно одной команды:
* выведет построчно состояние всех блоков, имя которых начинается с "Connect" Write to LCD Info = "{Status of Connect}"
Многострочный вывод, а так же трансляция свойств блоков в фигурных скобках "{}", должны быть заключены в двойные кавычки. Чтобы каждый раз не оформлять многострочную запись, можно использовать "\N" для перехода на новую строку.

Команда Write автоматически переключает экран в режим "текст и изображение" за исключением когда нужно вывести игровой скрипт (см. ниже).

Чтение и запись экрана
Новая, по сравнению с Easy Automatition, команда Text позволяет считывать и записывать любой экран блока целиком.
* чтение содержимого экрана в переменную Value of screen = Text of LCD Info * добавление заголовка и перезапись всего содержимого экрана Text of LCD Info = "Содержимое экрана \N\screen"
Запись на экран при помощи Text, в отличии от Write, производится без смены режима экрана. Например, если на экране в момент записи отображается системный скрипт типа "Гравитация", то он там и останется.
При записи с помощью Text транслируются только переменные. Свойства блоков, заключенных в фигурные скобки "{}", не обрабатываются.

Вывод игрового скрипта
Начиная с ver.1.3 EasPlay позволяет выводить на экран игровые скрипты типа часы, уровень гравитации, сетку горизонта, наличие цели и т.п. Для этого используется команда WriteScript с тем же синтаксисом, что и команда текстового вывода Write.
* выведет сетку горизонта на экран WriteScript to LCD info = TSS_ArtificialHorizon
Здесь после знака "=" указано внутри игровое имя скрипта, которое можно узнать, если установить нужный вам скрипт вручную, а затем через панель управления и вывести в область эха свойство Script
Echo = "{Script of LCD Info}"
Настройка вывода LCD
Позволяет настроить шрифт, цвет, выравнивание и другие параметры экрана (поверхности) для оформления вывода. С помощью этой линейки команд легко реализовать сценарий настройки параметров одного экрана по типу другого.

Часть команд линейки пересекаются с доступными свойствами обычной текстовой LCD-панели, но Easy Play делает их доступными не только для нее, но и для любой поверхности, номер которой указывается в квадратных скобках "[]":
* установить размер шрифта центрального экрана промышленного кокпита FontSize of Industrial Cockpit[1] = 4.5
Для настройки можно использовать следующие команды:

FontSize — размер шрифта, число с десятичной точкой от 0.1 до 10.0

FontFace — шрифт, обычно Debug, Monospace или любой доступный из списка в панели управления, имя шрифта контекстнозависимое

TextAlign — выравнивание текста на экране, одно из значений: Left, Right, Center

FontColor — цвет шрифта, RGB-триада с разделителем ":", например синий = 0:0:255

Padding — отступ текста от краев панели, десятичное число от 0 до 100

BgColor — цвет экрана, RGB-триада с разделителем ":", например красный = 255:0:0

BgRotate — угол вращения экрана, одно из значений: 0, 90, 180, 270 (только для LCD-панелей)

Image — изображение, размещаемое на экране, например, "Danger" - значек опасности. Полный список изображений приведен в панели управления при настройке экрана. Имя изображения контекстнозависимое.

Text — чтение/записи информации на экран (см. раздел "Запись и чтение LCD")

Script — имя системного скрипта, например "TSS_EnergyHydrogen" - энергия и водород. Полный список скриптов приведен в панели управления при настройке экрана. Имя скрипта контекстнозависимое.

Surface. Комплексная настройка экрана
Команда позволяет выполнить настройку основных параметров экрана (поверхности) одной строкой и устанавливать настройки одного экрана по типу другого.
* детальная настройка экрана FontFace of LCD Info = Debug FontSize of LCD Info = 3 FontColor of LCD Info = 255:255:200 TextAlign of LCD Info = Center Padding = 20 BgColor = 0:100:200 * настройка одной строкой, сокращения параметров упорядочены по детальным настройкам Surface of LCD Info = "ff=Debug|fs=3|fc=255:255:200|ta=center|tp=20|bc=0:100:200"
Присутствие всех параметров настройки в команде Surface необязательно, порядок их следования также не имеет значения. Разделитель параметров — вертикальная черта "|".

Такой подход позволяет написать простой сценарий настройки параметров одного экрана
по аналогии с другим экраном и вызвать его из панели управления ПБ Easy Play со двумя
параметрами: surset(Button HallL[0], Button HallR[1]), где первым указывается экран,
настройки которого нужно установить, а вторым — экран настройки которого нужно взять.
@surset { * читаем в переменную настройки 2-го экрана \x = Surface of \2 * устанавливаем по ним настройки первого Surface of \1 = \x }

А этот сценарий позволит установить все экраны 4-х кнопочной Sci-Fi с именем Button Right панели по типу 2-й кнопки панели с именем Buttons Left.
@but4 { \x = Surface of \2 Surface of \1[0] = \x Surface of \1[1] = \x Surface of \1[2] = \x Surface of \1[3] = \x }
Запуск сценария через строку аргументов ПБ: but4(Button Right, Buttons Left[1])
* цвет последней кнопки после выполнения сценария на тестовом корабле изменен вручную
HINT. Одинаковую настройку всех экранов 4-х кнопочных Sci-Fi панелей можно выполнить по первой кнопке с помощью but4(Sci-Fi Panel, Sci-Fi Panel), где Sci-Fi Panel — имя вашей панели.
Система меню на LCD
Начиная с ver.1.3 EasyPlay синтаксис команды Write дополнен суффиксом Menu, с помощью которого можно без труда организовать систему многоуровнего меню. Сценарий меню вы будете писать сами, а EasyPlay просто будет выводить указатель текущего пункта.

Синтаксис команды: WriteMenu(Index) to LCD[N] = "Text", где (Index) — число от 1, порядковый номер текущего пункта меню; LCD — имя блока LCD-панели или экрана кокпита; [N] — число от 0, порядковый номер экрана для мультиэкранных блоков (если не указано используется первый экран); Text — многострочный текст меню или текст с разделителем "новая строка" \N.
* выведет на панель с именем LCD Info текст, с указателем ">" перед первой строкой WriteMenu(1) to LCD Info = "Ship status Drone control Show horizon Exit from menu" * выведет тоже самое, здесь новая строка представлена разделителем \N WriteMenu(1) to LCD Info = "Ship status\NDrone control\NShow horizon\NExit from menu"
.
Здесь для вывода заголовка меню вместо WriteMenu используется команда WriteLineMenu, которая по аналогии с WriteLine просто добавляет вывод к текущему содержимому панели с новой строки. Соответственно WriteAddMenu добавит текст меню без переноса строки.

Сценарий двухуровнего меню
Для того, чтобы написать меню с помощью EasyPlay потребуется несколько переменных:
@var { * имя панели для вывода lcd = "LCD Info" * меню 1-го уровня main = "Ship status\NDrone control\NShow horizon\NExit from menu" * меню 2-го уровня invent = "Ship status Turret status Stock ammo Stock ingots Main menu" * текущие значения указателя пункта и текста выводимого меню mopt = 1 menu = "" x = 0 }

Теперь выведем меню на экран, чтобы получить то, что представлено на картинке выше. Для этого создадим @-блок с именем "menu" (или любым другим)
@menu { * при первом вызове текст меню пустой, поэтому помещаем в \menu текст главного меню if \menu = "" { \menu = \main } * эта команда подсчитывает количество строк в меню, чтобы перемещать указатель \x = TokenLine of menu * выводим заголовок и само меню Write to \lcd = "= Ship Control Menu =\N" WriteLineMenu(\mopt) to \lcd = \menu }

Вывести на экран меню можно запустив EasyPlay с аргументом menu через панель управления.
.
Займемся перемещением указателя, для этого в @menu добавим логику его обработки, для этого будем анализировать значение первого аргумента \1, переданного в сценарий в ():
@menu { if \menu = "" { \menu = \main } \x = TokenLine of menu * при выводе меню с аргументом menu(down) увеличим текущее значение указателя на 1 if \1 = "down" { \mopt = math(\mopt+1) if \mopt > \x { \mopt = 1 } * при выводе меню с аргументом menu(up) уменьшим текущее значение указателя на 1 } else if \1 = "up" { \mopt = math(\mopt-1) if \mopt = 0 { \mopt = \x } } Write to \lcd = "= Ship Control Menu =\N" WriteLineMenu(\mopt) to \lcd = \menu }

Теперь добавим логику выбора пункта и выхода из меню
@menu { if \menu = "" { \menu = \main } \x = TokenLine of menu if \1 = "down" { \mopt = math(\mopt+1) if \mopt > \x { \mopt = 1 } } else if \1 = "up" { \mopt = math(\mopt-1) if \mopt = 0 { \mopt = \x } * при обращении с аргументом menu(exit) через панель управления } else if \1 = "exit" { * очистим экран и остановим сценарий Write to \lcd = "" Stop * при обращении с аргументом menu(select) через панель управления } else if \1 = "select" { * если текущее значение в \menu соответствует меню 1-го уровня main if \menu = \main { * вызываем сценарий его обработки @menu_main * если текущее значение в \menu соответствует меню 2-го уровня invent } else if \menu = \invent { * вызываем сценарий его обработки, соответственно @menu_invent } } Write to \lcd = "= Ship Control Menu =\N" WriteLineMenu(\mopt) to \lcd = \menu }

Осталось написать сценарии обработки для каждого меню. Для этого можно анализировать текущее значение указателя в переменной \mopt, а можно содержимое строки меню, на который он в настоящий момент указывает. Сравнение производится с учетом регистра:
* сценарий обработки меню 1-го уровня, используем указатель @menu_main { * если указатель указывает на 1-й пункт, который отвечает за вызов меню 2-го уровня if \mopt = 1 { * устанавливаем указатель на первый пункт нового меню \mopt = 1 * помещаем в \menu текст меню второго уровня и возвращаемся в блок @menu для вывода \menu = \invent } else if \mopt = 3 { * если выбрана третья строка, выводим на экран системный скрипт сетки горизонта WriteScript to \lcd = TSS_ArtificialHorizon * и не возвращаемся в @menu, чтобы его вывод не перекрыл запущенный скрипт Stop } else { @menu(exit) } } * сценарий обработки меню 2-го уровня, анализируем строку, на которой стоит указатель @menu_invent { * эта команда позволяет получить значение строки по ее номеру в тексте меню \x = TokenLine[\mopt] of menu * если строка содержит "Ship" if \x ? "Ship" { * то запускаем сценарий вывода общего состояния корабля @ship_status Stop * если строка содержит "ingot" } else if \x ? "ingot" { * то выводим на экран результат инвентаризации слитков на гриде WriteLine to \lcd = "{Invent ingot[ * ] of MyGrid}" Stop * если строка содержит "ammo" } else if \x ? "ammo" { * то выводим на экран результат инвентаризации патронов на всем корабле, * включая все сабгриды, на тот случай, если есть кастомные турели WriteLine to \lcd = "{Invent ammo[ * ] of MyShip}" Stop * если строка содержит "Turret" } else if \x ? "Turret" { * выводим состояние турелей WriteLine to \lcd = "{Status Turret of MyGrid}" Stop } else if \x ? "menu" { \mopt = 1 \menu = \main } }

Вот как будет выглядеть экран при выборе 4-го пункта в меню 2-го уровня. Поскольку для вывода инвентаризации используется команда WriteLine, то ее вывод будет добавлен на экран ниже меню, что удобно, т.к. позволяет ориентироваться, что именно выводится, а меню при этом остается активным и вы можете сразу переместить указатель к другому пункту:

.
Собственно все. Осталось поместить обращение к основному сценарию в блоке @menu на цифровую панель станции управления кораблем и можно работать. Для этого сидя в кресле управления нужно нажать Ctrl+G и вызвать на экран панель настройки цифровых клавишь.

Затем последовательно перетащить на свободное место в панели иконку с изображением ПБ EasyPlay, выбрать в меню "Запустить" и ввести параметры обращения к меню:

.
Для #1 в поле "Аргумент" нужно ввести menu, это вызовет меню на экран LCD-панели
Для #2 в поле "Аргумент" нужно ввести menu(down), это переместит указатель вниз
Для #3 в поле "Аргумент" нужно ввести menu(up), это переместит указатель вверх
Для #4 в поле "Аргумент" нужно ввести menu(select), это выберет текущий пункт меню
Для #5 в поле "Аргумент" нужно ввести menu(exit), это завершит работу с меню и уберет его

Hint: логику управления можно сократить с 5-и цифровых клавиш до 2-х. Например, вывод меню на экран можно совместить с выбором в меню, а указатель перемещать только в одном направлении, т.к. согласно приведенному сценарию он будет перемещаться циклически. Кнопку выхода можно вообще убрать, поскольку в меню есть опция выхода.
Роторы, шарниры, поршни
Одной из самых полезных функций Easy Play является упрощенное управление перемещением динамических блоков при помощи одной команды вне зависимости от их текущего положения.

Роторы и шарниры поворачиваются на нужный угол с заданной скоростью при помощи команд Rotate и ShortRotate. Поршень выдвигается на заданную длину с заданной скорость при помощи команды Move. Например:
* повернуть ротор на 160 град. со скоростью 5 об./мин. против часовой стрелки Rotate MyRotor to 160 at -5 * повернуть ротор на -30 град. со скоростью 1 об./мин. направление вычисляется автоматически ShortRotate MyRotor to -30 at 1 * выдвинуть/задвинуть поршень на 7 со скоростью 1 Move MyPiston to 7 at 1
Команды не сокращаются и могут быть набраны в любом регистре. Все команды изменяют значения верхней и нижней границ блока — это нужно учитывать, если автоматизация использует так же стандартное действие "Reverse", доступное для динамических блоков этого типа. Если ротор или шарнир блокированы в момент выполнения команды, то блокировка будет снята автоматически.
При установке значений, превышающих допустимые, выводится сообщение об ошибке и сценарий останавливается, так как предполагается, что дальнейшее его выполнение связано с новой позицией блока.

Управление поршнем
Поршень перемещается при помощи команды Move MyPiston to Distance at Speed где MyPiston — имя поршня, выборки или группы поршней, Distance — расстояние, на которое нужно выдвинуть поршень, Speed — скорость с которой должен двигаться поршень.

Предельные расстояния для поршней малой и большой сетки и направление перемещения определяются автоматически. Текущее положение поршня определяется свойством Position.
if Position of MyPiston = 0 { Move MyPiston to 3.5 at 1 }

Поворот роторов и шарниров
Синтаксис команд Rotate и ShortRotate унаследован от Easy Automatition:

Rotate/ShortRotate MyRotor to Angle at Speed, где MyRotor — имя ротора, группы или выборки роторов, Angle — угол на который нужно повернуть (целое число от -360 до 360), Speed — скорость поворота (целое число от -30 до 30 для роторов большой сетки и от -60 до 60 для малой сетки). Положительное число скорости поворота выполнит поворот по часовой стрелке, а отрицательное — против часовой.

Команда ShortRotate поворачивает ротор на заданный угол по кратчайшему пути. Формула поиска минимального угла поворота изменена относительно оригинального скрипта.

Для шарниров используется тот же синтаксис, что и для роторов, но угол, на который можно
повернуть шарнир, устанавливается в диапазоне от -90 дл 90 град, а команда ShortRotate работает так же как и команда Rotate.

Текущий угол поворота шарнира или ротора можно узнать с помощью свойства Angle
if Angle of MyRotor = 90 { ShortRotate MyHinge to 30 at 1 }

Во избежании Clang-а, при завершении поворота желательно устанавливать скорость вращения равной нулю, а ротор или шарнир блокировать. Для ротора, угол которого установлен в ноль, команда блокировки может изменять значение текущего угла с 0 на 360 градусов. Это нужно учитывать при использовании логических выражений:
\x = cond(Angle of MyRotor = 0 | Angle of MyRotor = 360 : 0 : 1) * если ротор в нулевой позиции if Value of x = 0 { * выдвигаем поршень Move MyPiston to 5 at 1 }
Контроллер управления кораблем
Easy Play обеспечивает доступ к свойствам любого контроллера, который может управлять кораблем. Имя контроллера нужно указывать точно, или вместо имени можно попробовать использовать MyShip. В этом случае будет использован первый найденный контроллер, который конструктивно соединен с гридом на котором установлен программный блок Easy Play.

Используя MyShip в качестве имени, можно также устанавливать свойства контроллера, например Damp of MyShip = True - включить гасители корабля, но обращаться с этим нужно аккуратно. Например свойство AutoPilot есть только у блока удаленного управления и попытка установить его для кокпита приведет к 318 ошибке.

Свойства Operate & OperateAxis
Operate определяет, занимает ли персонаж указанный контроллер (сидит в кокпите, пилотском кресле, станции управления и т.п) или нет. Может быть сокращено до "Oper".

При использовании MyShip будет возвращено имя контроллера который в настоящий момент занимает персонаж или False, если ни один контроллер не занят. Можно использовать для автоматизации, связанной с присутствием персонажа на борту.
* если персонаж в кокпите if Oper of MyCockpit = True { * закрываем двери Close Door of MyGrid }

OperateAxis определяет использует ли персонаж клавиши управления кораблем по осям при помощи клавиш управления WASD. Возвращает True или False
@var { * определяет контроллер в котором находится персонаж cont = Operate of MyShip x = 0 } @test { \x = OperAxis of \cont * если кнопка управления WASD нажат выводим эхо if \x = True { Echo = "Operate!" } }

Группы команд
Несколько групп команд, позволяют определить текущие параметры корабля (скорость, массу, и т.д) и окружающего пространства (высоту над поверхностью планет, наличие гравитации и т.п)

Синтаксис команды: Группа Свойство of Имя_контроллера/MyShip, если вместо имени контроллера указано MyShip то берется первый доступный контроллер, который может управлять кораблем.

Порядок следования Группы и Свойства, а так же и регистр слов значения не имеет. Имя группы нужно указывать полностью, а свойства можно сокращать до первых 3-х символов (Nat вместо Natural, Alt вместо Altitude и.п.):

Группа Gravity — гравитация, число с десятичной точкой от 0, без ключа возвращает суммарную гравитацию с учетом искусственной и натуральной

Natural — натуральная гравитация планеты
Artificial — искусственная гравитация, которую дают генераторы гравитации корабля

Группа Planet — положение относительно планеты, при отсутствии натуральной гравитации или ключа возвращает -1

Position — триада GPS-координат центра ближайшей планеты
Elevation — триада GPS-координат позиции контроллера относительно центра планеты
Altitude — число с десятичной точкой, высота контроллера над поверхностью планеты

Группа Speed — без ключа возвращает базовую скорость корабля в м./сек

Linear — линейная скорость в м/сек
Angular — угловая скорость в рад./сек

Группа Mass — без ключа возвращает полную масса корабля в кг, включая пристыкованные через коннекторы гриды

Base — базовая масса корабля в кг.
Physical — полная масса корабля в кг. с учетом игрового мультипликатора массы груза

Группа Grid — информация и координаты

Name — имя корабля во вкладке "Инфо" системной панели (не сокращается)
SizeL — длина корабля в метрах (не сокращается)
SizeW — ширина корабля в метрах (не сокращается)
SizeH — высота корабля в метрах (не сокращается)
Park — имя_грида:имя_коннектора к которому припаркован корабль (не сокращается)
Position — триада GPS-координат центра масс грида, на котором установлен контроллер
Margin[NN] — триада GPS-координат границы грида, рассчитывается вверх от контроллера на удалении, равному NN метров или максимальной размерности грида по трем его осям ДхШхВ.
Если в момент исполнения команды в приемнике сообщений через радиоантенну есть данные в формате GPS, то расчет границы производится по вектору связывающему центр масс и GPS-координаты приемника. Такое решение позволяет безопасно автоматически подлететь к кораблю (см. "Обмен через радиоантенну").

Ниже приведен пример вывода параметров корабля на LCD-панель с использованием разных контроллеров, любой из которых можно использовать для получения нужных свойств:
* используется первый доступный контроллер \myname = Grid Name of MyShip * используется удаленное управление \mypos = Grid Pos of Remote Control * используется кокпит \mygrav = Art Gravity of MyCockpit \myspeed = Speed of MyShip \mycargo = math(Mass of MyShip - Base Mass of MyShip) Write to LCD Info = "\myname Длина: {Grid SizeL Of MyShip} м. Ширина: {Grid SizeW Of MyShip} м. Высота: {Grid SizeH Of MyShip} м. Скорость: \speed м/сек Вес груза: \mycargo кг Координаты: \mypos"
Автопилот. Автоматизация полета
Автоматизация обеспечивается блоками дистанционного управления и AI Flight (Move), который имеет более высокий приоритет, если у него включен "искусственный интеллект".

Управление автопилотом
Обеспечивается группой команд "Fly", для их использования на корабле должно быть установлен блок дистанционного управления. Перед выполнением команд, убедитесь, что ИИ AI Flight (Move) выключен: ActivateBehavior of <блок> = False, где <блок> — имя блока AI Flight.

Fly Start — включить автопилот

Fly Stop — выключить автопилот

Fly Clear — очистить список точек навигации, с ver.1.202.068 не использовать, команда нарушает работу автопилота, оставлена на будущее

Fly to GPS at Speed — добавить к списку точек навигации координаты GPS (с ver.1.202.068 заменить список) и ограничить скорость Speed — число с десятичной точкой от 0 до 100.

Так же устанавливается: направление полета — вперед, в один конец, а так же режимы "избегать столкновений" и "парковка". Примерный сценарий с установкой точки назначения для автопилота:
\coord = "GPS:База:-62664.81:-80178.37:-27915.08:#" Fly to \coord at 30 Fly Start

Для изменений настроек автопилота, определяемых командой Fly to, используйте стандартные свойства самого блока автопилота:
* отмена режима "избегать столкновения" CollisionAvoidance of MyRemote = False * отмена режима "парковка" DockingMode of MyRemote = False * вместо Fly Start можно активировать автопилот иначе AutoPilot of MyRemote = True
После достижения заданной точки она будет удалена из списка навигации автопилота.

Разворот на точку GPS
До ver.1.202.068 установка 0-й скорости для автопилота позволяло развернуть корабль по координатам точки назначения относительно ориентации блока дистанционного управления, после чего автопилот прекращал работу. Теперь автопилот не выключается, но задачу разворота из статического положения все же можно решить менее тривиальным способом:
* заносим GPS-координаты точки на которую нужно развернуться и устанавливаем скорость = 5 Fly to \coord at 5 * запоминаем текущие GPS-координаты блока удаленного управления \x = "{Grid Pos of Remote Control}" * запоминаем в переменную дистанцию от текущей точки здесь она равна 0 \y = Distance \x of Remote Control * запускаем автопилот Fly Start * корабль начнет разворот на месте на нужную точку и затем начнет движение * со скоростью 5 м/с, когда удаление от первоначальной точки превысит 3 метра When \y > 3 * выключаем автопилот Fly Stop
Этот сценарий хорошо работает в космосе, но в гравитации разворот происходит не на заданную точку, а в направлении ее проекции на поверхность планеты. Сама же точка может при этом оказаться выше или ниже корабля.
Инвентаризация корабля
Две команды Inventory и InventoryX (по аналогии с популярным скриптом Alutomatic LCDs 2.0) позволяют получить информацию о грузе корабля, находящемся в любых модулях, имеющих отсеки для хранения руд, слитков, компонентов, амуниции, патронов и т.п., которые отображаются в системной панели "Инвентарь".
Полная инвентаризация и вывод состояния корабля с помощью одного сценария Easy Play
Инвентаризацию можно проводить как целиком по сеткам MyShip, MyGrid, AllGrid, так и по отдельным блокам или группе блоков (см. "Выборка блоков и гриды").

Inventory выводит детальную информацию, а InventoryX только число. Обе команды допускают сокращение до трех символов с "x" в конце для последней.
* вернет число и название: 1203 Cobalt Inventory Ore[cobalt] of MyGrid Invent Ore[cobalt] of MyGrid Inv Ore[cobalt] of MyGrid * вернет только число: 1203 InventoryX Ore[cobalt] of MyGrid InventX Ore[cobalt] of MyGrid InvX Ore[cobalt] of MyGrid

Inventory выводит 6 групп игровых компонентов, названия которых можно сократить до первых 3-х символов.
  • components — компоненты
  • ores — руды
  • ingots — слитки
  • ammo — патроны
  • arm — оружие/инструметы
  • other — прочее
В квадратных скобках "[]" указывается либо звездочка "*" для вывода всех элементов группы, либо полное внутри игровое название конкретного элемента на английском языке. При запросе слитков вслед за ними в круглых скобках "()" будет указано количество руды того же типа.

При использовании "[*]" выводятся все элементы группы вне зависимости от их наличия. Чтобы не выводить элементы которых нет в инвентаре, следует установить invempty = false внутри кода скрипта EasyPlay.
Write to LCD Info = " < Патроны > {Invent ammo[*] of MyShip} < Уран > {Invent Uranium of AllGrid}"
Этот код выведет на LCD-панель все боеприпасы, имеющиеся на корабле, включая турели пристыкованных через коннекторы кораблей, и урановые слитки и руду только вашего корабля:
< Патроны >
1200 Gatling 25x184 mm
4300 Turret 56x45 mm
120 Missile 200 mm
< Уран >
345 Уран (2450)

В Easy Play патроны NATO 25x184 и NATO 56x45 выводятся как патроны для Гатлинга и
внутренней турели соответственно. Так их проще визуально контролировать.

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

Вы можете проводить также частичную инвентаризацию выборки или группы блоков. В этом
случае инвентаризация будет выполнена для MyShip.
* руда и слитки железа в очистительных заводах Write to Echo = "{Inv Iron of Refinery}" * стальные пластины во всех контейнерах Write to Echo = "{Inv Steel Plate of Container}" * стальные пластины без учета пристыкованных кораблей Write to Echo = "{Inv comp[Steel Plate] of AllGrid}" * количество льда в генераторах Write to Echo = "{Inv Ice of O2/H2 Generator}"
Названия элементов выводится на том языке, который установлен для локализации. Сортировка элементов групп выполняется только для внутри игровых названий на английском.
Перевод всех внутри игровых названий руд, компонентов, инструмента и т.п. вы можете найти в Обсуждениях к скрипту Easy Play
Вы можете написать любой сценарий инвентаризации, определив свой порядок вывода, и вызывать его всякий раз, когда требуется посмотреть наличие нужных элементов.

HINT. Если требуется постоянное обновление данных, как в Automatic LCDs 2.0, то просто заведите вызов сценария на таймер и замкните таймер на себя, но нужно понимать, что во-первых, ПБ Easy Play в каждый момент времени способен выполнять только один сценарий, а во-вторых, полная инвентаризация — достаточно затратная процедура. Обычно инвентаризации по запросу вполне достаточно для реальной игры.
Обмен через радиоантенну
Easy Play позволяет отправлять и принимать сообщения в радиусе действия радиоантенны,
исключая собственные антенны, антенны сабгридов и припаркованных через коннектор кораблей. ПБ Easy Play используется и как источник и как приемник сообщений.

Любой сценарий может отправлять и считывать данные из приемника сообщений. Этот игровой механизм называется Inter Grid Communication (Межсетевая коммуникация) — далее IGC.

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

Имя канала связи устанавливается в переменной igcTag в коде скрипта (по умолчанию "EasyPlay"). Рекомендую изменить его, если скрипт используется в кооперативной игре или на сервере, чтобы обмен данными между кораблями шел по индивидуальному каналу связи.

Для отправки сообщений антенна должна быть включена и для нее должно быть разрешено вещание. Для приема сообщений антенна должна быть включена, а состояние вещания значения не имеет. Кроме того, если вы для безопасности собираетесь включать антенну только на момент передачи данных, то требуется примерно 300 мс, чтобы она стала готова к передаче. Учитывайте это в своих сценариях обмена.

Чтение и отправка сообщений осуществляется с помощью команды Send:
* отправка через первую доступную антенну грида Send = "Hello" * отправка через антенну Antenna 1 Send to Antenna 1 = "Hello" * чтение сообщения из приемника Send of MyShip * очистка приемника сообщений Send Clear * очистка приемника и очереди сообщений Send Wipe
Easy Play не предоставляет протокол обмена данными. Единственно, что он делает при получении IGC сообщения — анализирует его на вхождение "@", и пытается выполнить блок кода, следующего за ним.

Например, прием SE Mothership:@gpspos(SE Escape Pod) равнозначен запуску программного блока со скриптом Easy Play, с аргументом gpspos(SE Escape Pod). Очевидно, что такой вызов @-блока должен завершать сообщение, возможные параметры должны разделяться запятой "," и быть заключены в круглые скобки "()".

Сценарий радиобмена
Примерный сценарий организации обмена данными между носителем SE Mothership и шатлом SE Escape Pod, позволяющем в автоматическом режиме вернуться к носителю по вектору шатла, получив по запросу его координаты в процессе радиобмена:
* код сценария SE Mothership * -------------------------- @var { * имя корабля = SE Mothership my = Grid Name of MyShip * GPS-координаты границы корабля pos = Grid Margin of MyShip } @gps_send { * отправка своих координат в формате GPS через канал связи Send = "\1:GPS:\my:\pos:#" * очиска приемника в ожидании следующего запроса Send Clear }
* код сценария SE Escape Pod ---------------------------- @var { * имя корабля = SE Escape Pod my = Grid Name of MyShip * текущие GPS-координаты шатла pos = Grid Position of MyShip * приемник сообщений rec = Send of MyShip } @fly_in { * отправка запроса на носитель с указанием своего имени \my, * текущих координат \pos и имени @-блока, который нужно выполнить Send = "SE Mothership:@gps_send(\my,GPS:\pos:#)" * ожидание ответа 0.5 сек Delay 500 * обращаясь к переменной rec, читаем сообщение если оно содержит имя "SE Escape Pod" if Value of rec ? \my { * то проверяем наличие префикса GPS-координат if Value of rec ? "GPS" { * если он есть, то заносим координаты в автопилот и устанавливаем макс. скорость 30 м/с Fly to \rec at 30 * запускаем автопилот и летим к носителю Fly Start } else { Write to Echo = "No GPS coordinates" } Send Clear } else { Write to Echo = "Space silent" } }

Этот сценарий, с небольшими дополнениями, реализован в примерных кораблях. Для того чтобы увидеть как он работает, нужно, управляя шатлом из кокпита, отлететь от материнского корабля на расстояние не менее 200 м. в любом направлении и выполнить для ПБ Easy Play шатла сценарий "fly_in" или нажать кнопку №6 на второй панели цифрового управления.
Расстояние до точки GPS
Свойство Distance
Определяет расстояние от центра масс корабля до указанной точки GPS-координат в метрах. Может быть сокращено до "Dist". Синтаксис команды: Distance GPS of MyShip, где GPS, должно включать триаду координат.
\pos = "-240416.621:-2342908.495:360086.708" * если дистанция до точки назначения меньше 500 м if Distance \pos of MyShip < 500 True { * включаем гасители, используя контроллер дистанционного управления DampenersOverride of Remote Control = True }

Команда Scan
Позволяет определить расстояние от камеры до объекта сканирования с помощью механизма Raycast игрового блока "Камера".

Синтаксис команды: Scan of MyCamera at Range, где MyCamera — точное имя блока камеры, а Range — расстояние в метрах, на которое производится сканирование:
* сканировать камерой с именем "Camera Left" на расстояние 15000 м. Scan of Camera Left at 15000

Результат сканирования помещается в CustomData указанной камеры в расширенном (с ver.1.3) формате GPS-координат, включающем префикс GPS, внутри игровой ID объекта, его имя, отношение с вами, размер, линейную скорость, тип объекта и координаты X:Y:Z
* ID Name Relate Size Vel Type X Y Z GPS:439630975968811834:Asteroid:Neutral:887:0.00:Asteroid:1002447.4:980106.9:1005785.5:

Имя объекта: для дружественных объектов будет выведено полное имя грида. Например, название корабля. Для вражеских объектов общее название на языке локализации игры. Например, "большая структура".

Тип объекта: Asteroid, CharacterHuman, CharacterOther, FloatingObject, LargeGrid, Meteor, Missile, None, Planet, SmallGrid, Unknow

Отношение с вами: Enemies, Neutral, Owner.

Размер объекта: целое число в метрах, если нужна повышенная точность, то можно указать количество знаков после десятичной точки в коде скрипта в переменной scanSize

Скорость объекта: линейная скорость в м/с с точностью до второго знака

Получить нужную характеристику можно с помощью токена (см. "Token. Извлечение из текста"):
Scan of Camera Lidar at 15000 \x = Data of Camera Lidar Write to \lcd = "Имя: {Token[3] of x}\N Тип: {Token[6] of x}\N Размер: {Token[5] of x} m"

Для передачи GPS-координат в автопилот то вместо Scan нужно использовать одну из следующих команд: Scan[Entity], Scan[Name], Scan[Type], Scan[Relate], которые поместят в поле "Свои данные" камеры координаты в обычном формате GPS (см. "Контроллер и автопилот"). Если сканирование не достигло цели, то поле "Свои данные" будет пустым.
При первом сканировании Raycast требует некоторое время на инициализацию (для 15 км задержка = 7.5 сек). После этого Raycast будет выполняться без задержек. Если переменная debug скрипта EasyPlay установлена true, то время задержки будет выводиться в область Echo подобно команде When.

Определение расстояния до цели
Совместное использование команд Scan и Distance позволяет легко определить дистанцию до цели сканирования:
* сканировать Camera на 10 км Scan of Camera at 10000 * результат в переменную gps \gps = Data of Camera * если gps содержит префикс "GPS", то if Value of gps ? GPS { * измеряем расстояние до GPS-координат \dist = Distance \gps of MyShip * и выводим его на дисплей Write to LCD Info = "Distance: \dist m" } else { Write to LCD Info = "No target" }

Замечание: камера должна быть открыта, а не скрыта за стеклом или прозрачным LCD-дисплеем, т.к. Raycast измеряет расстояние по лучу до ближайшего объекта.
Script. Свойства EasyPlay
Для доступа к внутренним переменным скрипта EasyPlay используется обращение к свойствам несуществующего блока c именем "Script" через которое можно получить их значение.

Lng. Текущая локализация
Может использоваться для вывода информации на LCD-панели в зависимости от локализации:
if Lng of Script = ru { Echo = Привет! } else { Echo = Hello! }

Rand. Случайная цифровая строка
В "[]" можно указать длину строки, без них возвращается случайное число из 3 цифр. Алгоритм генерации несложный, поэтому уникальность для коротких чисел не гарантируется
* выведет случайную последовательность из 5 цифр Echo = "{Rand[5] of Script}"

Sync. Системное время по модулю
Позволяет определить посекундное время наступления события путем вычисления значения по модулю от числа секунд Unix TimeStamp. Значение интервала в секундах указывается в "[]":
if Sync[5] of Script = 0 { Echo = "Прошло 5 сек с момента запуска" }
Может использоваться для управления запуском @-блоков с использованием игрового блока Таймер. См. раздел "Автоматизация по таймеру" Sync без "[]" вернет последнюю задержку по When, если в скобках указано не число, вернет текущий UnixTime в секундах.

UTC. Системное время
Системное время в секундах.
Echo = "{UTC of Script}"
Другие свойства и команды
Здесь описаны свойства и действия, которые не вошли в прочие разделы руководства.
  • AI — паттерны поведения блоков AI Offensive, AI Defensive и AI Basic
  • Jump — установка дальности прыжка прыжкового двигателя
  • Number — подсчет количества блоков выборки
  • Override — установка перехвата управления трастерами в %
  • Sound — мелодия динамика
  • Time — вывод локального время корабля по шаблону C#

AI. Паттерны поведения
Позволяет считать и установить значение из списка: Attack pattern для блока AI Offensive, Flee для блока AI Deffensive и Mission для блока AI Basic, rкоторые определяю программу поведения, передаваемую ими блоку управления полетом AI Flight.

Каждый AI-блок имеет свои предустановленные значения, которые не сокращаются:

Имя блока
--------------------------
AI Offensive (Combat)
Допустимое значение
------------------------------------------------------------------------------------------
CycleOrbit, StayAtRange, HitAndRun, Intersept
AI Defensive (Combat)
Always, Never, WhenTakingDamage, WhenTargetLocked
AI Basic (Task)
FollowPlayer, FollowHome, AutoPilot

* выведет текущую установку из списка Pattern Attac блока с именем AI Offensive Echo = "{AI of AI Offensive}" * установит значение в списке Mission блока с именем AI Basic AI of AI Basic = FollowHome

Jump. Прыжковый двигатель
Позволяет считать или установить дальность прыжка в метрах (километрах)
* выведет установленную дальность прыжка в метрах Echo = "{Jump of MyJump Drive}" * выведет установленную дальность прыжка в километрах и текущий статус Echo = "{Status of MyJump Drive}" * установит дальность прыжка в километрах Jump of MyJump Drive = 10 * стандартное свойство блока Jump Drive выведет дальность прыжка в %% Echo = "{JumpDistance of MyJump Drive}" * стандартное свойство блока Jump Drive установит дальность прыжка в %% JumpDistance of MyJump Drive = 30

Number. Подсчет количества блоков
Возвращает число равное количеству блоков с указанным именем или входящих в группу.
* общее количество турелей всех типов имя которых начинается с "Turret" Echo = "{Number of #Turret on MyShip}" * общее количество вооружения в группе "Weapons" Echo = "{Number of (Weapons)}"

Override. Перехват управления трастерами
Позволяет установить перехват управления трастерами в процентах, а не в kN, как это можно сделать при обращении к свойству "Override" обычным способом. Для установки укажите число от 0 до 100 и следующий за ним знак процента "%"
Over of Ion Thruster Forward = 50%

Sound. Мелодия динамика
Позволяет установить мелодию для динамика из "списка звуков". Полный список мелодий и звуковых эффектов приведен в панели управления при настройке динамика. Имя мелодии контекстно зависимое. Если мелодия не выбрана, то возвращается пустая строка "".
@sound { * считать в переменную игровое имя текущей мелодии \x = Sound of Dynamic Echo = Мелодия динамика: \x * установить новую мелодию Sound of Dynamic = SoundBlockAlert1 * проиграть PlaySound Dynamic }
Замечание: выбор установленного таким способом мелодия динамика может не отображаться в списке доступных мелодий в панели управления, но воспроизводится как надо.

Time. Локальное время корабля
Возвращает время в формате MM/DD/YYYY H:M, где MM = месяц, DD = день, YYYY = год, H = часы в 24-х часовом формате, M = минуты.
Echo = "Date: {Time of MyShip}"
Расширенный формат команды позволяет указать в квадратных скобках шаблон вывода даты и времени. Например Time[dd/MM/yy HH:mm:ss] выведет дату в международном формате и время в 24-х формате вместе с секундами. Возможные представления шаблонов можно посмотреть здесь[www.c-sharpcorner.com].
Автоматизация по таймеру
Для задач, требующих постоянного анализа состояния игровых блоков можно использовать автоматический вызов программного блока с параметром. Этот прием, который применялся в игру Space Engineers до 2018, когда блоки не умели самостоятельно перезапускаться.

Для его применения потребуется отдельный таймер в первый слот которого помещается ПБ EasyPlay, а во второй - таймер с командой "открыть".
Частота перезапуска задается временем задержки таймера и минимально может составлять 1 сек, чего вполне достаточно, чтобы решать таким способом большинство типичных задач, связанных с автоматизацией корабля.

Одной из таких задач, которую можно решить подобным способом является автоматическое закрытие дверей (AutoDoors). Ее можно легко выполнить с помощью EasyPlay не устанавливая отдельный ПБ для специального скрипта, которые можно найти в мастерской Steam:
@sync { * если хотя бы один блок имя которого начинается с Door имеет статут "Открыто" if Status of #Door on AllGrid = Open { * закрываем все двери Open_Off #Door on AllGrid } }
Если установить задержки таймера равной 2 сек. то этого будет достаточно, чтобы двери на корабли закрывались автоматически, не мешая персонажу проходить сквозь них.

Уточнение грида AllGrid позволит скрипту определять только те двери, которые находятся на корабле и игнорировать двери, когда корабль припаркован через коннектор к космической станции, на которой так же могут быть двери имя которых начинается с "Door"

Автоматическая инвентаризация
Другой популярной задачей является инвентаризация корабля, когда на LCD-панели выводится содержимое контейнеров, очистительных заводов, заполнение баков и пр. Не совсем понятно, зачем это нужно для автоматизации игрового процесса, но выглядит красиво. Эту задачу так же можно решить с помощью EasyPlay, добавив к приведенному выше коду еще одно условие:
@sync { if Status of #Door on AllGrid = Open { Open_Off #Door on AllGrid } * эта команда позволит обновлять вывод на LCD каждые 5 сек if Sync[5] of Script < 2 { Write to LCD Info = " -= Руда =- Inventory ores[*] of MyGrid -= Слитки =- Inventory ingot[*] of MyGrid" } }
По умолчанию инвентаризация блоков грида производится не чаще 5 сек, поэтому нет смысла нагружать ПБ EasyPlay посекундным обращением таймера, но есть один нюанс, связанный с вычислением интервала в 5 сек.

При выставлении задержки таймера в 2 сек, запуск сценария будет происходить во 2-ю, 4-ю, 6-ю и далее секунды. Команда Sync вычисляет значение по модулю от системного времени обращения к скрипту. Поэтому интервал в 5 секунд попадет в эту последовательность только каждую 10-ю секунду.

Чтобы избежать этого и используется условие "меньше 2", которое позволит выполнить сканирование инвентаря либо каждую 4-ю либо каждую 6-ю секунду, что не критично для задачи инвентаризации, но выполнять действия с точностью до секунды в реальной игре не получится. Это следует учитывать при анализе возможности решения задач автоматизации, связанных с временным периодом.

Замечание: поскольку в один момент времени ПБ EasyPlay может выполнять только один сценарий, то лучше использовать два программных блока, один из которых будет решать задачи по таймеру, а второй - прочие задачи не связанные со периодом времени. Демонстрацию автоматизации по таймеру вы можете найти на этом корабле:
https://steamcommunity.com/sharedfiles/filedetails/?id=2725165752
Программный таймер
Если требуется решать динамические задачи, связанные с программированием поведения корабля в бою, то обычного таймера, может оказаться недостаточно. В этом случае можно использовать вместо него отдельный программный блок, который будет запускать нужный сценарий с частотой 6 раз в секунду:
string pbn = "PB EasySync"; // имя блока EasyPlay, который управляет динамикой string arg = "status"; // имя сценария, который будет запускаться IMyProgrammableBlock sync = null; public Program() { Runtime.UpdateFrequency = UpdateFrequency.Update10; } public void Main(string argument, UpdateType updateSource) { if(sync == null) { List<IMyProgrammableBlock> pb = new List<IMyProgrammableBlock>(); GridTerminalSystem.GetBlocksOfType<IMyProgrammableBlock>(pb,b => b.CubeGrid == Me.CubeGrid && b.CustomName == pbn); if(pb.Count > 0) sync = pb[0]; } if(sync != null) sync.TryRun(arg); }
Просто скопируйте этот код С# в поле "Код" программного блока, который будет вместо таймера, и измените настройки на свои.
Отладка сценария
Для включения режима отладки @-блоков нужно установить значение переменной debug в коде скрипта Easy Play равным true. По умолчанию ход выполнения сценария выводится на экран программного блока.

Вы можете использовать для вывода любой экран (поверхность) для чего в переменной conLCD нужно указать имя блока с которого оно начинается и номер экрана (если требуется). Например, "Cockpit[1]" выведет диагностику на центральный экран промышленного кокпита.

Вывод команд осуществляется построчно с указанием имени @-блока и полного имени команды или свойства, которое было задействовано. Если в выражении участвует переменная, то ее имя с лидирующим обратным слэшем "\" будет выведено вслед за командой. Количество блоков, попавших в выборку, указывается в круглых скобках "()". Для команд Delay и When указывается время выполнения в секундах.
Отслеживание логики выполнения можно осуществлять по набору команд, которые были выполнены для внутри ветки If / Else. Команды, которые были выполнены, выводятся на консоль сразу после ключевого слова, а условия, которые были проигнорированы, выводятся одной строкой, содержащей только ключевое слово If/Else If/Else без показа команд, которые должны были быть выполнены.

Рекомпиляция кода производится всякий раз, когда вы изменяете поле "Свои данные" ПБ Easy Play. Время, затраченное на компиляцию выводится первой строкой в консоли. Дополнительно, в []-скобках выводится количество выполненных инструкций.
По умолчанию в SE допускается одновременное выполнение не более 50000 инструкций, при превышении это значения выдается системная ошибка "Скрипт слишком сложный...". Это призвано защитить игру от бесконечных циклов внутри кода, но т.к. EasyPlay представляет собой интерпретатор поля CustomData, то слишком длинный код в нем может вызвать эту ошибки на этапе компиляции.
Для отладки так же можно использовать команды Echo и Console с помощью которых можно просматривать промежуточные значения переменных в области Echo панели управления или прямо в консоли. Последнее бывает полезно для копирования результатов в буфер обмена, т.к. консольный вывод на экран доступен для редактирования через кнопку "Редактировать" для любой панели если установлен режим "текст и изображение":
@test { Console = "GPS:MyPos:{Grid Position of MyShip}:#" }
В примере выше осуществляется вывод на консоль текущих координат корабля в формате GPS. После выполнения в поле "Большой дисплей" ПБ Easy Play по кнопке "Редактировать" будет доступно что-то типа GPS:MyPos:-261248.412871745:-2350813.49051253:352906.455766861:#. Эту строку можно прямо скопировать из буфера обмена в системной панели "GPS" чтобы получить метку с текущими координатами, так как если бы вы задействовали там кнопку "Новая из текущей позиции".

Обработка ошибок
Ошибки бывают 2-х типов: критические (код ошибки больше 400) и некритические (код ошибки больше 300 и меньше 400).

Критические ошибки в основном возникают на этапе компиляции и блокируют выполнение сценария. На консоль в этом случае выводится только сообщение об ошибке, например, "E402> Дисбаланс {}". Локализовать такую ошибку не представляется возможным, поэтому искать ее в коде следует там, где были произведены последние изменения.

При возникновении некритичной ошибки ее код выводится напротив команды, которая содержит ошибку, но выполнение сценария не прерывается. Типичный пример такого сценария — отстрел ракет путем обращения к программному блоку управления ракетой. Если ракеты кончились, то очередное обращение вызовет ошибку с кодом 313, говорящую что блок с таким именем не найден и это никак не отразится на игровом процессе.

Вывод ошибок производится на языке локализации, если соответствующие данные установлены в поле "Клавиатура" ПБ Easy Play.

Системная ошибка
Возникает в случае внутренней ошибки Easy Play и делает неработоспособным программный блок. В случае ее возникновения в области Echo появляется системное сообщение компилятора C# и для продолжения работы всей автоматизации необходимо заново скомпилировать скрипт.
По сравнению с оригинальным скриптом, Easy Play более устойчив к системным ошибкам, но полностью исключить их не удастся, так как приходится обрабатывать пользовательские переменные, которые не всегда соответствуют нужному формату.
Оптимизация сценария
В разработке...
Локализация Easy Play
Локализация, т.е. перевод на язык, отличный от оригинального английского, реализована на уровне вывода системных сообщений, ошибок выполнения сценариев и названий игровых компонентов — руд, слитков, расходных материалов и т.п.

Установка локализации производится путем размещения в поле "Редактировать" клавиатуры программного блока Easy Play двух ini-блоков:
[sys] 100 = ru 101 = Свойство 102 = Действие ... [lng] Cobalt = Кобальт Gold = Золото Ice = Лед
Блок [sys] отвечает за вывод на консоль системных сообщений и ошибок. Он должен начинаться с указания префикса языка 100 = префикс, который указывается в коде скрипта Easy Play в перемененной language. При смене языка скрипт следует рекомпилировать.

Блок [lng] отвечает за вывод команд Inventory и Status. Это перевод внутри игровых названий большинства компонентов. Если этот блок отсутствует, то вывод осуществляется на английском.

Замечание: в настоящий момент есть только русская локализация, переводы на другие языки будут публиковаться в Steam Workshop в обсуждениях к скрипту по мере возможности.
Известные проблемы
1. Нельзя вывести "{" или "}" (одиночную фигурную скобку) в командах Write и Data — это будет приводить к ошибке баланса скобок при компиляции автоматизации.

2. Нельзя комментировать строки, содержащие " (двойные кавычки) — будет выведено сообщение об ошибке компиляции для следующей после такого комментария строки:
* Echo = "Test: \x" if \x > 0 { ... }
Для такого кода будет выдана ошибка 416, "Misuse IF/WHEN/ELSE"

3. В именах блоков не следует использовать ключевые слова if, else, when, of, at, to, on, MyShip, MyGrid, AllGrid — это может приводить к неправильной работе сценария. Например команда Start для блока с именем "Timer of Alert" просто не будет выполнена из-за наличия в имени блока ключевого слова of, а логика if/else выдаст некритичную ошибку выполнения:
* этот сценарий работать не будет if OnOff Timer of Alert = True { Start Timer of Alert }

4. Фиксирование значение переменной через ту же самую переменную может привести к краху скрипта. Используйте двойные кавычки, чтобы избежать этого:
\x = Position of MyPiston \x = "\x"
Попытка получить значение токена в ту же переменную приведет к краху скрипта:
\x = "1:2:3" \x = Token[1] of x

5. Вложенные @-замыкания не поддерживаются и могут привести к неправильной работе или краху скрипта.

6. Запись на кнопочную панель без экрана приведет к краху скрипта, поскольку Sci-Fi панель и обычная панель не отличаются по свойствам.

51 коментара
PuPsIk 27 юли 2024 в 12:27 
Спасибо)
Survival Ready  [автор] 27 юли 2024 в 11:05 
Задержку выполнения дает команда Delay в мс. Например, Delay 1000 даст задержку в 1 сек. Если вы хотите стрелять из ванильных ракетных установок попеременно с помощью ЛКМ, то для этого есть отдельный скрипт Salvo
PuPsIk 27 юли 2024 в 3:56 
How to make a delay between rocket launchers if there are many of them, so that they do not launch at the same time?
PuPsIk 27 юли 2024 в 3:38 
Как правильно поставить задержку между командами, к примеру я хочу что бы из разный ракетных установок ракеты вылетали с задержкой, а не сразу?
Survival Ready  [автор] 25 окт. 2023 в 13:05 
Yes, this is possible with the help of the Mass of MyShip command. This is the total mass of the ship, taking into account the in-game cargo mass multiplier.
DasKrusty 23 окт. 2023 в 22:22 
Is it possible to get the weight of the ship, want to use math to control torque of hinges based on how heavy the craft is.
Survival Ready  [автор] 12 септ. 2023 в 11:56 
In this case, you can use a variable with the name in double quotes

@var {
Engine = "Hydrogen Engine"
}

@shutdown {
onOff_Off \Engine
}
DasKrusty 11 септ. 2023 в 4:18 
Another question, for my ground craft or wheel craft, I always set up some basic functions to shut down and start up the craft, but I want to make the script work without having to change naming, make the script generic, would like to do the following:

@variables {
Engine = Hydrogen Engine of MyGrid
or
Engine = "Hydrogen Engine"
}

@shutdown {
OnOff_Off Engine
}

Will either of the variables work to make this happen, I suppose I can do this without the variable? Any suggestions?
Survival Ready  [автор] 22 авг. 2023 в 11:07 
If the block is offline or destroyed above the destruction limit, then the Status command returns Offline or Damaged. The Echo command cannot be read, it only outputs data for debugging or diagnostic purposes.
DasKrusty 20 авг. 2023 в 0:08 
Out of interest, how do you read a status from the echo section? If I wanted to read the result of Echo = "{Status of UTG-7 Rotor Trailer Hitch}", how would I turn that into an if command?