Вопросы по Lua скриптингу

Общая тема для вопросов по разработке скриптов на языке программирования Lua, в частности под MoonLoader.
  • Задавая вопрос, убедитесь, что его нет в списке частых вопросов и что на него ещё не отвечали (воспользуйтесь поиском).
  • Поищите ответ в теме посвященной разработке Lua скриптов в MoonLoader
  • Отвечая, убедитесь, что ваш ответ корректен.
  • Старайтесь как можно точнее выразить мысль, а если проблема связана с кодом, то обязательно прикрепите его к сообщению, используя блок [code=lua]здесь мог бы быть ваш код[/code].
  • Если вопрос связан с MoonLoader-ом первым делом желательно поискать решение на wiki.

Частые вопросы

Как научиться писать скрипты? С чего начать?
Информация - Гайд - Всё о Lua скриптинге для MoonLoader(https://blast.hk/threads/22707/)
Как вывести текст на русском? Вместо русского текста у меня какие-то каракули.
Изменить кодировку файла скрипта на Windows-1251. В Atom: комбинация клавиш Ctrl+Shift+U, в Notepad++: меню Кодировки -> Кодировки -> Кириллица -> Windows-1251.
Как получить транспорт, в котором сидит игрок?
Lua:
local veh = storeCarCharIsInNoSave(PLAYER_PED)
Как получить свой id или id другого игрока?
Lua:
local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- получить свой ид
local _, id = sampGetPlayerIdByCharHandle(ped) -- получить ид другого игрока. ped - это хендл персонажа
Как проверить, что строка содержит какой-то текст?
Lua:
if string.find(str, 'текст', 1, true) then
-- строка str содержит "текст"
end
Как эмулировать нажатие игровой клавиши?
Lua:
local game_keys = require 'game.keys' -- где-нибудь в начале скрипта вне функции main

setGameKeyState(game_keys.player.FIREWEAPON, -1) -- будет сэмулировано нажатие клавиши атаки
Все иды клавиш находятся в файле moonloader/lib/game/keys.lua.
Подробнее о функции setGameKeyState здесь: lua - setgamekeystate | BlastHack — DEV_WIKI(https://www.blast.hk/wiki/lua:setgamekeystate)
Как получить id другого игрока, в которого целюсь я?
Lua:
local valid, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) -- получить хендл персонажа, в которого целится игрок
if valid and doesCharExist(ped) then -- если цель есть и персонаж существует
  local result, id = sampGetPlayerIdByCharHandle(ped) -- получить samp-ид игрока по хендлу персонажа
  if result then -- проверить, прошло ли получение ида успешно
    -- здесь любые действия с полученным идом игрока
  end
end
Как зарегистрировать команду чата SAMP?
Lua:
-- До бесконечного цикла/задержки
sampRegisterChatCommand("mycommand", function (param)
     -- param будет содержать весь текст введенный после команды, чтобы разделить его на аргументы используйте string.match()
    sampAddChatMessage("MyCMD", -1)
end)
Крашит игру при вызове sampSendChat. Как это исправить?
Это происходит из-за бага в SAMPFUNCS, когда производится попытка отправки пакета определенными функциями изнутри события исходящих RPC и пакетов. Исправления для этого бага нет, но есть способ не провоцировать его. Вызов sampSendChat изнутри обработчика исходящих RPC/пакетов нужно обернуть в скриптовый поток с нулевой задержкой:
Lua:
function onSendRpc(id)
  -- крашит:
  -- sampSendChat('Send RPC: ' .. id)

  -- норм:
  lua_thread.create(function()
    wait(0)
    sampSendChat('Send RPC: ' .. id)
  end)
end
 
Последнее редактирование:

Double Tap Inside

Известный
Проверенный
1,899
1,244
Как получить PID текущей GTA?

Братан, всё ахуенно, но я не шарю ffi, я даже не понимаю синтаксис ffi.cdef [[ typedef.....
Надо сделать функцию типа int = getCurrentProcessId(). Именно текущего, а не активного. Тось надо pid под которым(я так думаю) мунлодер запущен.

-----
Вот надыбал где-то код (для CS:GO), если можете, то помогите, думаю в нем есть то, что мне надо
Lua:
local ffi = require("ffi")
-- Include definitions for some WinAPI functions.
ffi.cdef(io.open("./winapi.h", "r"):read("*a"))

function GetProcessID(ExecutableFilename)
     -- Get a handle to the process list.
     local ProcessList = ffi.C.CreateToolhelp32Snapshot(0x2, 0)

     local CurrentProcess = ffi.new("PROCESSENTRY32")
     CurrentProcess.dwSize = ffi.sizeof("PROCESSENTRY32")

     while (ffi.C.Process32Next(ProcessList, CurrentProcess) == 1) do
         if (ffi.string(CurrentProcess.szExeFile):lower() == ExecutableFilename:lower()) then
             -- Free resources and return the process ID.
             ffi.C.CloseHandle(ProcessList)
             return tonumber(CurrentProcess.th32ProcessID)
         end
     end

     -- Free resources and return nothing.
     ffi.C.CloseHandle(ProcessList)
end

А вот и файл winapi.h
Lua:
1 typedef void* HANDLE;
2 typedef int BOOL;
3 typedef unsigned char BYTE;
4 typedef unsigned long DWORD;
5
6 typedef struct PROCESSENTRY32 {
7     DWORD dwSize;
8     DWORD cntUsage;
9     DWORD th32ProcessID;
10     DWORD th32DefaultHeapID;
11     DWORD th32ModuleID;
12     DWORD cntThreads;
13     DWORD th32ParentProcessID;
14     long pcPriClassBase;
15     DWORD dwFlags;
16     char szExeFile[260];
17 } PROCESSENTRY32;
18
19 typedef struct MODULEENTRY32 {
20     DWORD dwSize;
21     DWORD th32ModuleID;
22     DWORD th32ProcessID;
23     DWORD GlblcntUsage;
24     DWORD ProccntUsage;
25     BYTE* modBaseAddr;
26     DWORD modBaseSize;
27     HANDLE hModule;
28     char szModule[256];
29     char szExePath[260];
30 } MODULEENTRY32;
31
32 void Sleep(DWORD dwMilliseconds);
33
34 HANDLE __stdcall OpenProcess(DWORD dwDesiredAccess, int bInheritHandle, DWORD dwProcessId);
35 int __stdcall CloseHandle(HANDLE hObject);
36
37 typedef PROCESSENTRY32* LPPROCESSENTRY32;
38 typedef MODULEENTRY32* LPMODULEENTRY32;
39
40 BOOL __stdcall Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
41 BOOL __stdcall Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
42
43 HANDLE __stdcall CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
44
45 int __stdcall ReadProcessMemory(HANDLE hProcess, void* lpBaseAddress, void* lpBuffer, size_t nSize, size_t* lpNumberOfBytesRead);
46 int __stdcall WriteProcessMemory(HANDLE hProcess, void* lpBaseAddress, void* lpBuffer, size_t nSize, size_t* lpNumberOfBytesWritten);
47
48 DWORD __stdcall WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
49
50 __declspec(dllimport) short __stdcall GetAsyncKeyState(int vKey);

Помогите рачку сделать это =) пожалуйста

В итоге этот код возвращает PID первой попавшейся GTA из запущеных, а как получить именно текущего GTA? Может в луа где-то есть PID...
 

chikibamboni95

Известный
58
2
Много раз видел, но не могу найти.. Как через команду получить 2 и более переменных?
 

Nagenbl4

Новичок
107
2
Нужно вывести 3 переменные из function sampev.onShowDialog(dialogid, dialogstyle, title, b1, b2, text) и вставить их в function imgui.OnDrawFrame() .
Как?
 

штейн

Известный
Проверенный
1,001
687
Нужно вывести 3 переменные из function sampev.onShowDialog(dialogid, dialogstyle, title, b1, b2, text) и вставить их в function imgui.OnDrawFrame() .
Как?
объяви эти три переменные как глобальные (xui1 = 123, xui2 = 456, xui3 = 789) и используй в другой функции??
 

Lil Xean

о да моя госпожа
212
225
(error) test.lua: opcode '00A0' call caused an unhandled exception
stack traceback:
[C]: in function 'getCharCoordinates'
E:\GTA San Andreas123\moonloader\test.lua:14: in function <E:\GTA San Andreas123\moonloader\test.lua:6>
[ML] (error) test.lua: Script died due to an error. (097603FC)
Lua:
sampRegisterChatCommand('flyy', function(arg)
            if arg ~= nil then
                playerId = tonumber(arg)
                local ped = sampGetCharHandleBySampPlayerId(playerId)
                if isCharInAnyCar(PLAYER_PED) then
                    local car = storeCarCharIsInNoSave(PLAYER_PED)
                    local carid = sampGetVehicleIdByCarHandle(car)
                    local X,Y,Z = getCharCoordinates(ped)
                    print(X,Y,Z)
                end
            end              
    end)
 

.Makarov.

Известный
190
35
Здравствуйте. Нужна помощь с проверкой на ник из таблицы в диалоге.
Вот сама таблица:
Lua:
acceptnicks = {
"Типа первый ник",
"Типа второй ник",
"Типа третий ник",
"Ну и четвертый ник"
}
Вот сама проверка:
Lua:
if not scriptcheck then
    if dialogId == 235 then
        for _,checkname in ipairs(acceptnicks) do
            if string.find(text, checkname) then
                sampAddChatMessage("Успешно, Ваш ник есть в таблице",-1)
                return false
            else
                sampAddChatMessage("Увы, не судьба(",-1)
                return false
            end
        end
    end
end
Ну так вот в чем вся суть проблемы. Если мой ник находится первый в таблице. Мне пишет "Успешно, Ваш ник есть в таблице". Но а если второй, третий, четвертый - пишет мол "Увы, не судьба(". Как сделать чтоб при открытии 235 диалога (/stats), искало ник в таблице до тех пор, пока не найдет ник с диалога. А не останавливалось на первом. Заранее спасибо
 

Petr_Sergeevich

Известный
Проверенный
707
296
(error) test.lua: opcode '00A0' call caused an unhandled exception
stack traceback:
[C]: in function 'getCharCoordinates'
E:\GTA San Andreas123\moonloader\test.lua:14: in function <E:\GTA San Andreas123\moonloader\test.lua:6>
[ML] (error) test.lua: Script died due to an error. (097603FC)
Lua:
sampRegisterChatCommand('flyy', function(arg)
            if arg ~= nil then
                playerId = tonumber(arg)
                local ped = sampGetCharHandleBySampPlayerId(playerId)
                if isCharInAnyCar(PLAYER_PED) then
                    local car = storeCarCharIsInNoSave(PLAYER_PED)
                    local carid = sampGetVehicleIdByCarHandle(car)
                    local X,Y,Z = getCharCoordinates(ped)
                    print(X,Y,Z)
                end
            end          
    end)
bool result, Ped ped = sampGetCharHandleBySampPlayerId(int id)

Здравствуйте. Нужна помощь с проверкой на ник из таблицы в диалоге.
Вот сама таблица:
Lua:
acceptnicks = {
"Типа первый ник",
"Типа второй ник",
"Типа третий ник",
"Ну и четвертый ник"
}
Вот сама проверка:
Lua:
if not scriptcheck then
    if dialogId == 235 then
        for _,checkname in ipairs(acceptnicks) do
            if string.find(text, checkname) then
                sampAddChatMessage("Успешно, Ваш ник есть в таблице",-1)
                return false
            else
                sampAddChatMessage("Увы, не судьба(",-1)
                return false
            end
        end
    end
end
Ну так вот в чем вся суть проблемы. Если мой ник находится первый в таблице. Мне пишет "Успешно, Ваш ник есть в таблице". Но а если второй, третий, четвертый - пишет мол "Увы, не судьба(". Как сделать чтоб при открытии 235 диалога (/stats), искало ник в таблице до тех пор, пока не найдет ник с диалога. А не останавливалось на первом. Заранее спасибо

Lua:
-- ...
if dialogId == 235 then
    sampAddChatMessage(isNicknameFound(text) and "Успех" or "Провал", -1)
    return false
end
-- ...

function isNicknameFound(text)
    for i = 1, #acceptnicks do
        if text:find(acceptnicks[i], 1, true) then
            return true
        end
    end
    return false
end
 
  • Нравится
Реакции: .Makarov. и Lil Xean

dhhh

Известный
51
1
Lua:
local main_window_state = imgui.ImBool(false)
local test_text_buffer = imgui.ImBuffer(256)
local cd = imgui.ImBool(false)
local checkboxes = imgui.ImBool(false)


function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    gg = lua_thread.create_suspended(onShowDialog)
    sampRegisterChatCommand("gos", gos)
    imgui.Process = false
    while true do
    wait(0)
        if main_window_state.v == false then
            imgui.Process = false
        end

    end
end
function gos(arg)
main_window_state.v = not main_window_state.v
imgui.Process = main_window_state.v
end
function imgui.OnDrawFrame()
    local cb = imgui.ImBool(false)
imgui.Begin("Binder GOS", main_window_state)
imgui.InputText(u8"Введите текст", test_text_buffer)
imgui.Text("TEXT")
if imgui.Checkbox(u8("текст"), checkboxes) then
    gg:run()
end
imgui.End()
end
function onShowDialog(dialogId)
    sampAddChatMessage(dialogId, -1)
end
Почему ид диалога не выводится?
 

штейн

Известный
Проверенный
1,001
687
Lua:
local main_window_state = imgui.ImBool(false)
local test_text_buffer = imgui.ImBuffer(256)
local cd = imgui.ImBool(false)
local checkboxes = imgui.ImBool(false)


function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    gg = lua_thread.create_suspended(onShowDialog)
    sampRegisterChatCommand("gos", gos)
    imgui.Process = false
    while true do
    wait(0)
        if main_window_state.v == false then
            imgui.Process = false
        end

    end
end
function gos(arg)
main_window_state.v = not main_window_state.v
imgui.Process = main_window_state.v
end
function imgui.OnDrawFrame()
    local cb = imgui.ImBool(false)
imgui.Begin("Binder GOS", main_window_state)
imgui.InputText(u8"Введите текст", test_text_buffer)
imgui.Text("TEXT")
if imgui.Checkbox(u8("текст"), checkboxes) then
    gg:run()
end
imgui.End()
end
function onShowDialog(dialogId)
    sampAddChatMessage(dialogId, -1)
end
Почему ид диалога не выводится?
local sampev = require 'lib.samp.events'

function sampev.onShowDialog(dialogId)
 

Petr_Sergeevich

Известный
Проверенный
707
296
Lua:
local main_window_state = imgui.ImBool(false)
local test_text_buffer = imgui.ImBuffer(256)
local cd = imgui.ImBool(false)
local checkboxes = imgui.ImBool(false)


function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    gg = lua_thread.create_suspended(onShowDialog)
    sampRegisterChatCommand("gos", gos)
    imgui.Process = false
    while true do
    wait(0)
        if main_window_state.v == false then
            imgui.Process = false
        end

    end
end
function gos(arg)
main_window_state.v = not main_window_state.v
imgui.Process = main_window_state.v
end
function imgui.OnDrawFrame()
    local cb = imgui.ImBool(false)
imgui.Begin("Binder GOS", main_window_state)
imgui.InputText(u8"Введите текст", test_text_buffer)
imgui.Text("TEXT")
if imgui.Checkbox(u8("текст"), checkboxes) then
    gg:run()
end
imgui.End()
end
function onShowDialog(dialogId)
    sampAddChatMessage(dialogId, -1)
end
Почему ид диалога не выводится?
Многое в разделе вопросов можно встретить, но это просто пиздец)
Рекомендую ознакомиться лишний раз с основными темами по разработке, лишним явно не будет.
https://blast.hk/threads/19292/, https://blast.hk/threads/14624/, https://blast.hk/threads/22707/, https://blast.hk/threads/13315/
Lua:
-- Подключение библиотек, модулей
local sampev = require 'lib.samp.events'

-- Положение окна ImGUI
local isMenuActive = imgui.ImBool(false)
-- Буфер для хранения текста
local textBuffer = imgui.ImBuffer(256)
-- Значение чекбокса
local isPressed = imgui.ImBool(false)
-- Переменная, которая будет хранить последний отображенный ID диалога
local lastDialogID = -1

-- Подробнее в SAMP.lua (ссылку приложил)
function sampev.onShowDialog(id, style, title, b1, b2, text)
    lastDialogID = id
end

function imgui.OnDrawFrame()
    imgui.Begin("Binder GOS", isMenuActive)
        -- Поле для ввода текста
        imgui.InputText(u8("Введите текст"), textBuffer)

        -- Обычный текст
        imgui.Text(u8("Обычный текст"))

        -- Чекбокс
        if imgui.Checkbox(u8("Чекбокс"), isPressed) then
            sampAddChatMessage(("Последний id: %s"):format(lastDialogID), -1)
        end
    imgui.End()
end

function main()
    while not isSampAvailable() do wait(0) end
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
 
    sampRegisterChatCommand("gos", function()
        isMenuActive.v = not isMenuActive.v
    end)
 
    while true do
        wait(0)
        imgui.Process = isMenuActive.v
    end
end