ERM => Lua FAQ - Printable Version +- Wake of Gods Forum | Форум Во Имя Богов (http://wforum.heroes35.net) +-- Forum: Герои Меча и Магии 3.5 WoG/ERA (/forumdisplay.php?fid=99) +--- Forum: Моды (/forumdisplay.php?fid=104) +---- Forum: ЭРА / ERA (/forumdisplay.php?fid=182) +---- Thread: ERM => Lua FAQ (/showthread.php?tid=5171) |
ERM => Lua FAQ - Berserker - 05.01.2018 15:46 Чтение данных по адресу Code: local mem = require('era.mem') Запись данных по адресу Code: mem.u8(адрес, значение) -- 1 байт 0..255 RE: ERM => Lua FAQ - Berserker - 05.01.2018 16:11 Обработка событий Ниже представлена таблица соответствия ЕРМ триггеров и новых именованных событий: Code: BA0 'OnBeforeBattle' Для подписки на события используется функция era.on из модуля era. function era.on (eventName, eventHandler, opts) Функция принимает три аргумента: имя события, функцию-обработчик и опции в виде таблицы (не обязательно). Возможные опции: Code: { Обработчики событий выполняются в порядке их приоритета и регистрации. Обработчики с низким приоритетом выполняются первее, с более высоким — позднее. С одинаковым приоритетом — в порядке регистрации. Пример. Code: era.on('OnHeroScreenMouseClick', function (event, handler, eventName) Обработчик получает следующие аргументы при вызове: event — для событий, генерируемых Эрой и плагинами — указатель на следующую структуру: Code: typedef struct TEvent { Для событий, генерируемых скриптами Lua для скриптов Lua — произвольная таблица. handler — вызываемая функция-обработчик. Позволяет применять рекурсию для анонимных функций или отписываться от обработки события. eventName — имя текущего события. Указанные выше параметры являются опциональными. Минимизированный пример выше: Code: era.on('OnHeroScreenMouseClick', function () Внимание! По умолчанию события, регистрируемые через era.on являются удаляемыми — обработчики будут удаляться при загрузке/старте новой игры, как это происходит и с ЕРМ-триггерами. Системные плагины могут использовать аналогичную функцию era.bind для регистрации обработчика, который не будет удалён никогда. Отписка от событий Помимо возможности установить одноразовый обработчик через era.on('...', handler, { oneTime = true }), имеется возможность полностью удалить определённый обработчик, передав в функцию era.off имя события и старую функцию-обработчик. Code: era.on('OnHeroScreenMouseClick', function (event, handler, eventName) Если обработчик — локальная именованная функция, то можно видоизменить пример: Code: local function MyHandler () Динамическое добавление/удаление обработчиков во время обработки событий При наступлении события создаётся полная копия его обработчиков, отсортированная в порядке приоритетов и даты регистрации. Любые добавления удаления обработчиков повлияют на новые генерации события, но не на текущее. Это значит, что нельзя в рамках одного и того же события отключить другой обработчик для данного события. Отключённый обработчик будет выполнен 1 раз, поскольку при генерации события была получена его копия. Пример. Code: local function MyHandler2 () Обработчик 1 выполняется до обработчика 2, так как у них одинаковые приоритеты, а он был зарегистрирован первым. Обработчик 1 сразу же отключает обработчик 2, но только для будущих генераций событий. В текущей генерации уже создана копия списка обработчиков (обработчик 1, обработчик 2). Поэтому при множественных щелчках в окне героя получим сообщения: Привет 1 Привет 2 Привет 1 Привет 1 Привет 1... RE: ERM => Lua FAQ - Berserker - 05.01.2018 17:04 Выполнение ЕРМ команд/ресиверов Для выполнения ЕРМ кода и доступа к ЕРМ-переменным используется модуль era.erm. Code: local erm = require('era.erm') Модуль позволяет использовать себя как функцию, передавая строку ЕРМ команд, разделённых ";" и без ведущих "!!". Code: erm('HE-1:C0/0/?y1/?y2; IF:M^Слот 0. Тип: %Y1. Количество: %Y2.^') Для доступа к ЕРМ-памяти используются таблицы erm.v, erm.z, erm.y, erm.e, erm.f (логические значения). Таблицы ведут себя как обычные индексированные массивы. Code: erm.v[7] = 600 -- записали 600 в v7 Дополнительно доступен метод :addr(индекс), возвращающий адрес ЕРМ-переменной в виде обычного числа. Code: print('Адрес e50: ' .. erm.e:addr(50)) Модуль erm содержит методы hero(id) и currHero() для получения доступа к объектам героя по его ID или текущему герою (полный аналог HE-1). У возвращаемого объекта имеется метод .w(индекс, значение?) для доступа к w-переменным героя. Code: local hero = erm.hero(30) -- получили героя с id = 30 RE: ERM => Lua FAQ - Berserker - 06.01.2018 03:43 Сохранение и загрузка данных Хранение данных в сохранённых играх может понадобиться как системным скриптам, так и обычным. ЕРМ-память сохраняется и загружается автоматически. Lua-данные для сохранения рекомендуется хранить в одной таблице. Нужно подписаться на события сохранения и загрузки, в которых вызвать функции, сохраняющие таблицу под уникальным именем или загружающие таблицу по уникальному имени. Для примера создадим таблицу с данными, которые нужно хранить в сохранённых играх: Code: local save = { После чего подпишемся на два события, в которых будем сохранять/загружать таблицу save: Code: era.on('OnLuaSavegameWrite', function () OnLuaSavegameWrite возникает, когда нужно записывать таблицу в сохранёнку. Для этого используется функция era.writeSavegame(таблица, уникальное имя). При загрузке игры (событие OnLuaSavegameRead) мы получаем таблицу по уникальному имени. Конструкция "or {}" возвращает пустую таблицу, если era.readSavegame вернула nil (данные не найдены). Такой подход позволяет загружать сохранённую игру, для которой скрипт ранее не использовался. Соответственно, далее идёт проверка на существование поля в таблице. Если поле отсутствует (старая версия скрипта или сохранение без скрипта), то ему присваивается значение по умолчанию. Теперь можно работать с save.mithril как обычной переменной: выводить количество мифрила, увеличивать/уменьшать и т.д. Примечание: в реальном примере мифрил лучше хранить для каждого игрока: local mithril = {0, 0, 0, 0, 0, 0, 0, 0} |