Wake of Gods Forum | Форум Во Имя Богов
Lua. Руководства - 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: Lua. Руководства (/showthread.php?tid=5170)


Lua. Руководства - Berserker - 05.01.2018 04:39

Скрипты Lua располагаются в папке Data\Scripts или "Имя мода\Data\Scripts" и имеют расширение *.lua.

Библиотечные скрипты располагаются в подпапке libs и libs\[имя библиотеки], например: libs\era\*.lua.
Библиотечные скрипты подключаются через require "имя" или require "имя подпапки в libs.имя файла без расширения". Пример: require "era.mem" для libs\era\mem.lua

Скрипты бывают системными и обычными. Системные загружаются только один раз при событии OnBeforeWoG (до создания окна и выполнения кода инициализации WoG) и работают всю игру, как привычные плагины. Обычные скрипты работают схоже с ЕРМ скриптами.

Системные скрипты имеют двойное расширение *.sys.lua и загружаются в алфавитном порядке. Первым загружается скрипт _core_.sys.lua, поскольку его имя начинается с подчёркивания.

Пример
Data\Scripts\test.sys.lua
Code:
print("Работает!")

Глобальная функция print использует системные диалоги (MessageBox) для отображения сообщений, пока не будет создано игровое окно. После чего функция отображает сообщения в виде внутриигровых окошек аналогично команде ЕРМ IF:M. Помимо этого, функция позволяет выводить в отладочном виде содержимое любых переменных (таблиц, cdata, логических и т.д.), что делает её безопасным и удобным средством для отладки. Если передать функции более одного аргумента, аргументы будут объединены пробелом.


RE: Lua. Руководства - Berserker - 05.01.2018 15:21

Системное программирование.

Работа с памятью.

Для низкоуровневого доступа к памяти можно использовать модуль era.mem

Code:
function mem.float (ptr, value)
function mem.double (ptr, value)
function mem.i32 (ptr, value)
function mem.i16 (ptr, value)
function mem.i8 (ptr, value)
function mem.u32 (ptr, value)
function mem.u16 (ptr, value)
function mem.u8 (ptr, value)

Указанный набор функций позволяет считывать данные по числовому адресу (если опущен второй аргумент) или записывать (если оба аргумента присутствуют).

i = integer, целочисленный
u = unsigned integer, беззнаковое целое число
Число после символа — размер данных в битах.
float и double позволяют работать с float32 и float64 (числа с плавающей запятой).

Пример
Data\Scripts\test.sys.lua
Code:
local mem = require('era.mem') -- загрузили модуль era.mem и сохранили его в локальной переменной

mem.i32(0x887668, 777)        -- записали 777 в v1 как целое 4-байтное число со знаком
local byte = mem.u8(0x401000) -- считали байт по адресу 0x401000

Другие полезные функции:

function mem.addr (ptr)
Преобразовывает адрес в виде ffi.cdata в обычное число. Возвращает обычное число в неизменном виде.

function mem.ptr (ptr)
Преобазовывает адрес или указатель в void*-указатель типа ffi.cdata

function mem.val (ptr)
Принимает адрес или указатель. Возвращает объединение (union) типа ffi.cdata:

Code:
union {
  int        v;
  void*      ptr;
  float*     f32;
  double*    f64;
  int32_t*   i32;
  uint32_t*  u32;
  int16_t*   i16;
  uint16_t*  u16;
  int8_t*    i8;
  uint8_t*   u8;
  char*      text;
}

Данное объединение позволяет изменять адрес указателя как обычное число (поле v) и получать типизированные данные по адресу.

Пример.
Code:
local v1 = mem.val(0x887668)
v1.f32[0] = 3.14 -- записали в v1 (адрес ЕРМ-переменной) число 3.14 ординарной точности

Доступен метод :str, аналогичный mem.str, позволяющий трактовать объединение как строку.
Code:
v1:str('Hi!') -- записывать в первые байты переменной v1 значение 'Hi'\0

function mem.ofs (ptr, offset)
По адресу/указателю и смещению возвращает новый адрес типа void*.
Пример: mem.ofs(0x400000, 0x1000)

function mem.str (ptr, str, bufSize)
Читает или записывает строку по адресу ptr. Последний аргумент — опциональный размер буфера, отведённый под строку.

Пример.
Code:
local text = mem.str(0x500000)      -- прочитать нуль-терминированную строку по адресу 0x500000
mem.str(0x500000, 'Привет, мир', 4) -- записать строку 'При'\0 по тому же адресу, ограничить размер буфера 4-мя символами, включая #0

Для удобства и повышения скорости работы модуль предоставляет готовые псевдонимы для популярных типов данных языка C:

Code:
mem.pvoid   = ffi.typeof('void*')
mem.pchar   = ffi.typeof('char*');
mem.intptr  = ffi.typeof('intptr_t')
mem.pfloat  = ffi.typeof('float*')
mem.pdouble = ffi.typeof('double*')
mem.pi32    = ffi.typeof('int32_t*')
mem.pi16    = ffi.typeof('int16_t*')
mem.pi8     = ffi.typeof('int8_t*')
mem.pu32    = ffi.typeof('uint32_t*')
mem.pu16    = ffi.typeof('uint16_t*')
mem.pu8     = ffi.typeof('uint8_t*')