Skip to content

Lua API

Artem Dzhemesiuk edited this page May 11, 2023 · 18 revisions

SuperMod позволяет использовать Lua-скрипты в модах для расширения функционала игры. Инструкция по загрузке Lua-скрипта находится на странице Модлоадер



Настройка SDK

Для удобной разработки модов SuperMod включает в себя SDK для Visual Studio Code, которое предоставляет подсказки по существующим функциям и параметрам в API.

Шаги установки SDK
  1. Скачать supermod-sdk.zip нужной версии. Последняя тут
  2. Распаковать папку в любое место на диске
  3. В Visual Studio Code в разделе Extensions скачать плагин Lua от sumneko

    lua-plugin

  4. Открыть настройки Visual Studio Code

    vsc-extensions

  5. В поиск по настройкам вписать @ext:sumneko.lua Library, найти параметр Lua > Workspace: Library

    add-library

  6. Нажать Add item
  7. Вписать путь к распакованной папке, и нажать OK



Доступные глобальные коллбеки

При объявлении функций с определенными названиями SuperMod будет вызывать их автоматически в определенных условиях


render

Эта функция будет выполняться каждый кадр

Пример
function render()
    print("Рендер!")
end

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


renderUi

Эта функция будет выполняться при отрисовке интерфейса мода в Dear ImGui. Полезна для добваления своих элементов в интерфейс мода

Пример
local imgui = require("imgui")
function renderUi()
    imgui.Text("Тестовый текст")
end

Отображает строку "Тестовый текст" в интерфейсе мода



Типы данных

vector2

Двумерные координаты, используются например для обозначнения позиции элемента в окне

Конструктор и параметры

Название аргумента Тип Обязателен? Описание
x Число Да Координата X (по горизонтали)
y Число Да Координата Y (по вертикали)
Пример
local vec = vector2(50, 100)
print("Координата X: " .. vec.x)

Выводит 50 в консоль


vector3

Трёхмерные координаты, используются например для обозначнения позиции обьекта в мире

Конструктор и параметры

Название аргумента Тип Обязателен? Описание
x Число Да Координата X (по горизонтали)
y Число Да Координата Y (по вертикали)
z Число Да Координата Z (в глубину)
Пример
local vec = vector3(50, 100, 150)
print("Координата Z: " .. vec.z)

Выводит 100 в консоль


rect

Двумерный прямоугольник, используется для обозначения какой-либо зоны на двумерной плоскости (например в мире, или в окне)

Конструктор и параметры

Название аргумента Тип Обязателен? Описание
left Число Да Левая координата по оси X (по горизонтали)
top Число Да Верхняя координата по оси Y (по вертикали)
right Число Да Правая координата по оси X (по горизонтали)
bottom Число Да Нижняя координата по оси Y (по вертикали)

ModInfo

Информация о моде

Параметры

Название аргумента Тип Обязателен? Описание
id Строка Да Идентификатор мода
title Строка Да Название мода
author Строка Нет Автор мода
version Строка Нет Версия мода
basePath Строка Да Путь к моду
luaScript Строка Нет Название файла Lua-скрипта
gameVersions Массив чисел Нет Массив поддерживаемых версий игры



Глобальные функции скриптов

wait

Ставит выполнение кода на паузу на указанное колчество времени

⚠️ Эта функция ставит на паузу выполнение всего текущего потока. SuperMod выполняется внутри потока игры, поэтому использование такой задержки приведет к паузе выполнения всей игры.

Аргументы

Название аргумента Тип Обязателен? Описание
time Число Да Время задержки, в милилсекундах
Пример
print("Первое сообщение")
wait(1000)
print("Второе сообщение")

"Второе сообщение" появляется через одну секунду после первого


currentTimestamp

Получает количество миллисекунд прошедших с 1 января 1970 года.

Возвращает

Число - Количество миллисекунд

Пример
print(currentTimestamp())

Выводит количество миллисекунд в консоль


log.info

Выводит сообщение в консоль (категория INFO)

Аргументы

Название аргумента Тип Обязателен? Описание
msg Строка Да Сообщение для вывода в консоль
Пример
log.info("Тестовое сообщение")

log.debug

Выводит сообщение фиолетового цвета в консоль (категория DEBUG)

Аргументы

Название аргумента Тип Обязателен? Описание
msg Строка Да Сообщение для вывода в консоль
Пример
log.debug("Тестовое сообщение")

log.warn

Выводит сообщение предупреждения жёлтого цвета в консоль (категория WARN)

Аргументы

Название аргумента Тип Обязателен? Описание
msg Строка Да Сообщение для вывода в консоль
Пример
log.warn("Тестовое сообщение")

log.error

Выводит сообщение ошибки в консоль (категория ERROR)

Аргументы

Название аргумента Тип Обязателен? Описание
msg Строка Да Сообщение для вывода в консоль
Пример
log.error("Тестовое сообщение")

log.game

Выводит сообщение в консоль (категория GAME)

Аргументы

Название аргумента Тип Обязателен? Описание
msg Строка Да Сообщение для вывода в консоль
Пример
log.game("Тестовое сообщение")

math.clamp

Ограничивает значение между нижней и верхней границей. Если значение меньше минимального - возвращает минимальное. Если больше максимального - возвращает максимальное.

Аргументы

Название аргумента Тип Обязателен? Описание
val Число Да Текущее значение
from Число Да Минимальное значение
to Число Да Максимальное значение

Возвращает

Число - Результат

Пример
print(math.clamp(0.4, 0, 1))
print(math.clamp(-2, 0, 1))
print(math.clamp(1.1, 0, 1))

Выводит в консоль числа: 0.4, 0, 1



Глобальные функции работы с игрой

game.isGameLoaded

Возвращает true, если игра уже загружена. Иначе, возвращает false.

Возвращает

Булево - Загружена ли уже игра

Пример
if game.isGameLoaded() then
    print("Игра уже загружена!")
end

game.world.getCamZoom

Получает текущий зум игрового мира в процентах

Возвращает

Число - Зум мира в процентах (т.е. при зуме 100% функция вернёт 100)

Пример
print("Текущий зум: " .. game.world.getCamZoom .. "%")

game.world.screenToWorld

Получает мировые координаты на определенной точке окна

Аргументы

Название аргумента Тип Обязателен? Описание
coords vector2 Да Координаты в окне

Возвращает

vector2 - Координаты в мире

Пример
print("Координаты верхнего левого угла экрана: " .. game.world.screenToWorld(vector2(0, 0)))

game.world.worldToScreen

Получает координаты окна, на которых отображается определенная точка в мире

Аргументы

Название аргумента Тип Обязателен? Описание
coords vector2 Да Координаты в мире

Возвращает

vector2 - Координаты в окне

Пример
print("Нулевые координаты мира отображаются на: " .. game.world.worldToScreen(vector2(0, 0)))

game.world.getCamWorldRect

Получает рамки окна игры в игровом мире

Возвращает

rect - Область мира видимая в окне игры, в мировых координатах

Пример
print("Область мира видимая в окне: " .. game.world.getCamWorldRect(vector2(0, 0)))



Модуль timers

Этот модуль позволяет планировать выполнение кода по заданному времени

Подключение модуля:

local timers = require("timers")

timers.setTimeout

Выполняет код один раз через заданное количество времени

Аргументы

Название аргумента Тип Обязателен? Описание
fn Функция Да Функция, которая будет выполнена
delay Число Да Через сколько миллисекунд должна быть выполнена функция

Возвращает

Число - ID таймера, может быть использовано для его отмены

Пример
local timers = require("timers")
timers.setTimeout(function()
    print("Привет!")
end, 2000)

Выведет "Привет!" в консоль через две секунды


timers.setInterval

Выполняет код бесконечное количество раз с заданным интервалом

Аргументы

Название аргумента Тип Обязателен? Описание
fn Функция Да Функция, которая будет выполнена
delay Число Да Интервал выполнения функции, в миллисекундах

Возвращает

Число - ID таймера, может быть использовано для его отмены

Пример
local timers = require("timers")
timers.setInterval(function() 
    print("Привет!")
end, 2000)

Будет выводить "Привет!" в консоль каждые две секунды


timers.clearTimer

Отменяет выполнение таймера

Аргументы

Название аргумента Тип Обязателен? Описание
id Число Да ID таймера, который будет отменён
Пример
local timers = require("timers")

local timerID = timers.setInterval(function() 
    print("Привет!")
end, 2000)

timers.setTimeout(function() 
    timers.clearTimer(timerID)
end, 10000)

Будет выводить "Привет!" в консоль каждые две секунды в течении 10 секунд (через 10 секунд таймер выводящий "Привет!" отменяется)



Модуль imgui

Этот модуль позволяет рисовать интерфейсы внутри игры

Подключение модуля:

local imgui = require("imgui")

Это обёртка над API библиотеки Dear ImGui. Названия методов сохранены, -> в C++ становится : в Lua

Для отрисовки компонентов внутри меню мода, используйте renderUi

В местах, где ImGui ожидает буффер или ссылку на данные используйте ffi.new("тип данных[1]") для инициализации буффера. Для большей информации, см. LuaJIT Docs



Модуль events

Этот модуль позволяет подписываться на ивенты

Подключение модуля и пример использования:

local events = require("events")
events.on("_unload", function()
    print("Мод выгружен!")
end)

Для списка всех ивентов см. Lua Events

Это обёртка над API библиотеки Dear ImGui. Названия методов сохранены, -> в C++ становится : в Lua

Для отрисовки компонентов внутри меню мода, используйте renderUi

В местах, где ImGui ожидает буффер или ссылку на данные используйте ffi.new("тип данных[1]") для инициализации буффера. Для большей информации, см. LuaJIT Docs



Модуль config

Этот модуль позволяет сохранять определенные данные в файл конфигурации

Подключение модуля:

local config = require("config")

⚠️ Методы, отделённые от config с помощью : вместо . должны быть выполнены на конкретном обьекте конфигурации, а не на самом config.
Например, метод config:getString в реальном коде может быть вызван как config.mod:getString.
См. примеры отдельных методов для лучшего понимания.

config.mod

В этом параметре расположен приватный объект конфигурации для текущего мода. Конфигурация в этом обьекте нужна только для использования скриптами мода и не используется самим SuperMod

Пример
local config = require("config")

config.mod:set("test", 123)
config.save()

Записывает значение 123 в ключ test


config.save

Сохраняет весь файл конфигурации. Если не выполнить - после перезапуска игры данных не будет

Пример
local config = require("config")

config.mod:set("test", 123)
config.save()

Записывает значение 123 в ключ test и сохраняет конфигурацию


config:set

Записывает значение в объект конфигурции по заданному ключу

Аргументы

Название аргумента Тип Обязателен? Описание
key Строка Да Ключ в обьекте конфигурации
value Строка, число или булеан Да Записываемое значение
Пример
local config = require("config")

config.mod:set("test", 123)
config.save()
print(config.mod:getNumber("test"))

Записывает в конфиг значение 123 по ключу test, получает его из конфига и выводит в консоль


config:has

Проверяет, существует ли значение в объекте конфигурции по заданному ключу. Возвращает true если значение существует, или false если нет.

Аргументы

Название аргумента Тип Обязателен? Описание
key Строка Да Ключ в обьекте конфигурации
Пример
local config = require("config")

if not config.mod:has("test") then
   config.mod:set("test", 123)
   config.save()
end

Если в конфиге нет значения по ключу test - записывает по нему значение 123


config:getString

Получает строковое значение из обьекта конфигурации по заданному ключу

Аргументы

Название аргумента Тип Обязателен? Описание
key Строка Да Ключ в обьекте конфигурации

Возвращает

Строка - Записанное в конфигурации значение или пустую строку, если значение отсутствует

Пример
local config = require("config")

print(config.mod:getString("test"))

Выводит в консоль строковое значение, которое хранится по ключу test


config:getNumber

Получает численное значение из обьекта конфигурации по заданному ключу

Аргументы

Название аргумента Тип Обязателен? Описание
key Строка Да Ключ в обьекте конфигурации

Возвращает

Число - Записанное в конфигурации значение или 0, если значение отсутствует

Пример
local config = require("config")

print(config.mod:getNumber("test"))

Выводит в консоль численное значение, которое хранится по ключу test


config:getBoolean

Получает булево значение из обьекта конфигурации по заданному ключу

Аргументы

Название аргумента Тип Обязателен? Описание
key Строка Да Ключ в обьекте конфигурации

Возвращает

Булеан - Записанное в конфигурации значение или false, если значение отсутствует

Пример
local config = require("config")

print(config.mod:getBoolean("test"))

Выводит в консоль булево значение, которое хранится по ключу test


config:getObject

Получает вложенный объект из обьекта конфигурации по заданному ключу

Аргументы

Название аргумента Тип Обязателен? Описание
key Строка Да Ключ в обьекте конфигурации

Возвращает

Объект - Вложенный объект

Пример
local config = require("config")

local nested = config.mod:getObject("testObject")

nested:set("test", 123)
config.save()
print(nested:getNumber("test"))

Записывает значение 123 по ключу test во вложенный объект testObject



Модуль memory

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

Подключение модуля:

local memory = require("memory")

memory.at

Создает новый объект Memory по заданному адресу или паттерну.

Аргументы

Название аргумента Тип Обязателен? Описание
location Число или строка Да Паттерн или адрес в памяти

Возвращает

Объект Memory.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678

memory:add

Возвращает новый объект memory, добавляя указанный смещение к адресу

Аргументы

Название аргумента Тип Обязателен? Описание
offset Число Да Смещение от прошлого адреса (в байтах)

Возвращает

Объект memory - новый объект memory с адресом, смещённым на указанное количество байтов

Пример
local memory = require("memory")
local newMemory = memory:add(4)
-- В этом случае, newMemory будет указывать на адрес, смещённый на 4 байта от исходного адреса memory

memory:getFunction

Возвращает функцию по текущему адресу

Аргументы

Название аргумента Тип Обязателен? Описание
functionType C-тип Да Тип функции в виде C-декларации

Возвращает

Функция - функция, находящаяся по текущему адресу в памяти

Пример
local memory = require("memory")
local func = memory:getFunction("int (*)()")
-- В этом случае, func будет функцией, находящейся по текущему адресу в памяти memory

memory:getAs

Возвращает указатель в виде указанного типа

Аргументы

Название аргумента Тип Обязателен? Описание
type C-тип Да Тип данных в виде C-декларации

Возвращает

C-данные - указатель на данные в памяти, интерпретированные в виде указанного типа

Пример
local memory = require("memory")
local data = memory:getAs("int")
-- В этом случае, data будет указателем на данные в памяти, интерпретированные как int

memory:call

Вызывает функцию по текущему адресу

Аргументы

Название аргумента Тип Обязателен? Описание
functionType C-тип Да Тип функции в виде C-декларации
... any Нет Аргументы функции

Возвращает

any - результат вызова функции

Пример
local memory =```lua
require("memory")
local result = memory:call("int (*)()")
-- В этом случае, result будет результатом вызова функции, находящейся по текущему адресу в памяти memory

memory:readAs

Читает данные по адресу, используя указанный тип

Аргументы

Название аргумента Тип Обязателен? Описание
type C-тип Да Тип данных в виде C-декларации

Возвращает

C-данные - данные, прочитанные по текущему адресу в памяти, интерпретированные в виде указанного типа

Пример
local memory = require("memory")
local data = memory:readAs("int")
-- В этом случае, data будут данными, прочитанными по текущему адресу в памяти memory, интерпретированными как int

memory:readOffset

Читает адрес (int32) по текущему адресу и возвращает объект memory с новым адресом

Возвращает

Объект memory - новый объект memory с адресом, прочитанным по текущему адресу в памяти

Пример
local memory = require("memory")
local newMemory = memory:readOffset()
-- В этом случае, newMemory будет объектом memory с адресом, прочитанным по текущему адресу в памяти memory

memory:readNearCall

Читает инструкцию вызова по относительному адресу (opcode E8) и возвращает объект Memory с адресом вызываемой функции.

Возвращает

Объект Memory.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local callMem = mem:readNearCall()  -- Читаем инструкцию вызова и получаем новый объект Memory

memory:readInt64 / memory:readLong

Читает int64 число по текущему адресу (8 байт)

Возвращает

Число.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local number = mem:readInt64()  -- Читаем int64 по текущему адресу

memory:readInt32 / memory:readInt / memory:readDword

Читает int32 число по текущему адресу (4 байта)

Возвращает

Число.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local number = mem:readInt32()  -- Читаем int32 по текущему адресу

memory:readInt16 / memory:readShort / memory:readWord

Читает int16 число по текущему адресу (2 байта)

Возвращает

Число.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local number = mem:readInt16()  -- Читаем int16 по текущему адресу

memory:readInt8 / memory:readByte / memory:readChar

Читает int8 число по текущему адресу (1 байт)

Возвращает

Число.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local number = mem:readInt8()  -- Читаем int8 по текущему адресу

memory:readFloat / memory:readSingle

Читает float (число с плавающей точкой) по текущему адресу (4 байта)

Возвращает

Число.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local number = mem:readFloat()  -- Читаем float по текущему адресу

memory:readDouble

Читает double (число с плавающей точкой) по текущему адресу (8 байт)

Возвращает

Число.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678local number = mem:readDouble()  -- Читаем double по текущему адресу

memory:readBool

Читает bool по текущему адресу (4 байта)

Возвращает

Логическое значение (boolean).

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local boolValue = mem:readBool()  -- Читаем bool по текущему адресу

memory:readSBool

Читает короткий bool по текущему адресу (1 байт)

Возвращает

Логическое значение (boolean).

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local boolValue = mem:readSBool()  -- Читаем короткий bool по текущему адресу

memory:readString

Читает строку по текущему адресу

Аргументы

Название аргумента Тип Обязателен? Описание
length Число Нет Длина строки, если не указана - читает до NULL байта

Возвращает

Строка.

Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
local string = mem:readString(10)  -- Читаем строку длиной 10 символов по текущему адресу

memory:writeInt64 / memory:writeLong

Записывает int64 число по текущему адресу (8 байт)

Аргументы

Название аргумента Тип Обязателен? Описание
value Число Да Значение, которое нужно записать
Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
mem:writeInt64(1234567890)  -- Записываем int64 значение по текущему адресу

## `memory:writeInt32` / `memory:writeInt` / `memory:writeDword`

Записывает int32 число по текущему адресу (4 байта)

Аргументы

Название аргумента Тип Обязателен? Описание
value Число Да Значение, которое нужно записать
Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
mem:writeInt32(123456)  -- Записываем int32 значение по текущему адресу

memory:writeInt16 / memory:writeShort / memory:writeWord

Записывает int16 число по текущему адресу (2 байта)

Аргументы

Название аргумента Тип Обязателен? Описание
value Число Да Значение, которое нужно записать
Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
mem:writeInt16(1234)  -- Записываем int16 значение по текущему адресу

memory:writeInt8 / memory:writeByte / memory:writeChar

Записывает int8 число по текущему адресу (1 байт)

Аргументы

Название аргумента Тип Обязателен? Описание
value Число Да Значение, которое нужно записать
Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
mem:writeInt8(123)  -- Записываем int8 значение по текущему адресу

memory:writeFloat / memory:writeSingle

Записывает float (число с плавающей точкой) по текущему адресу (4 байта)

Аргументы

Название аргумента Тип Обязателен? Описание
value Число Да Значение, которое нужно записать
Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
mem:writeFloat(123.456)  -- Записываем float значение по текущему адресу

memory:writeDouble

Записывает double (число с плавающей точкой) по текущему адресу (8 байт)

Аргументы

Название аргумента Тип Обязателен? Описание
value Число Да Значение, которое нужно записать
Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
mem:writeDouble(123.456789)  -- Записываем double значение по текущему адресу

memory:writeString

Записывает строку по текущему адресу

Аргументы

Название аргумента Тип Обязателен? Описание
string Строка Да Строка, которую нужно записать
Пример
local memory = require("memory")
local mem = memory.at(0x12345678)  -- Создаем новый объект Memory по адресу 0x12345678
mem:writeString("Привет, мир!")  -- Записываем строку по текущему адресу

memory.toU16

Конвертирует UTF8 строку (char*) в UTF16 строку (wchar_t*)

Аргументы

Название аргумента Тип Обязателен? Описание
str Строка / C-данные Да Строка, которую нужно конвертировать

Возвращает

C-данные - сконвертированная строка

Пример
local memory = require("memory")
local utf16Str = memory.toU16("Привет, мир!")  -- Конвертируем строку в UTF16

memory.toU16Array

Конвертирует UTF8 строку (char*) в массив UTF-16 байтов (полезно для ffi.new с wchar_t)

Аргументы

Название аргумента Тип Обязателен? Описание
str Строка / C-данные Да Строка, которую нужно конвертировать

Возвращает

Массив чисел - сконвертированная строка в формате массива байтов

Пример
local memory = require("memory")
local utf16Array = memory.toU16Array("Привет, мир!")  -- Конвертируем строку в массив UTF16 байтов

memory.toU8

Конвертирует UTF16 строку (wchar_t*) в UTF8 строку (char*)

Аргументы

Название аргумента Тип Обязателен? Описание
str Строка / C-данные Да Строка, которую нужно конвертировать

Возвращает

C-данные - сконвертированная строка

Пример
local memory = require("memory")
local utf8Str = memory.toU8(utf16Str)  -- Конвертируем строку из UTF16 в UTF8

memory:hook

Регистрирует хук-функцию на текущий адрес

Аргументы

Название аргумента Тип Обязателен? Описание
type C-тип Да Тип данных для хука
fn Функция Да Функция, которая будет выполнена

Возвращает

Hook - объект хука, содержащий поля destroyed (был ли хук удалён), orig (оригинальная функция), и метод destroy (удаляет и деактивирует хук).

Пример
local memory = require("memory")

local hook;
hook = memory.at("55 8B EC 51 0F B6 45"):hook("int32_t (__cdecl *)(char)", function(a1)
    print("Хук выполнен!")
    return hook.orig(a1);
end)
-- Выводит "Хук выполнен!" в консоль каждый раз когда игра скрывает или показывает курсор мыши
Clone this wiki locally