Вопросы по 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
 
Последнее редактирование:

winrare

Новичок
75
1
в раксампе или реверсить
Скачал raksamp, в файле netrpc.cpp нашел этот код (мне нужно отловить вывод TextDraw):
C++:
void ScrShowTextDraw(RPCParameters *rpcParams)
{
    PCHAR Data = reinterpret_cast<PCHAR>(rpcParams->input);
    int iBitLength = rpcParams->numberOfBitsOfData;

    RakNet::BitStream bsData((unsigned char *)Data,(iBitLength/8)+1,false);

    WORD wTextID;
    TEXT_DRAW_TRANSMIT TextDrawTransmit;

    CHAR cText[1024];
    unsigned short cTextLen = 0;

    bsData.Read(wTextID);
    bsData.Read((PCHAR)&TextDrawTransmit, sizeof(TEXT_DRAW_TRANSMIT));
    bsData.Read(cTextLen);
    bsData.Read(cText, cTextLen);
    cText[cTextLen] = '\0';

    if(settings.uiTextDrawsLogging != 0)
        SaveTextDrawData(wTextID, &TextDrawTransmit, cText);
  
    if(TextDrawTransmit.byteSelectable)
        Log("[SELECTABLE-TEXTDRAW] ID: %d, Text: %s.", wTextID, cText);
}
Как теперь определить, какие параметры используются в событии? Здесь все в куче, ничего не понятно.
 

Roman13371

Новичок
6
2
Помогите.
Только начал разбираться в LUA, не понимаю в чем ошибка.

Lua:
nick, nomer, text = string.match(text, "(%a+_%a+).(%d+).(.+)")

Даже через
Lua:
if string.find(

ищу нужное мне слово, но ничего не находится.

Знаю, что ошибка в первой строке, но как исправить не знаю, может кто поможет.

В игре в чате выводит так: %s[%d]: %s (ник, ид, текст)
 
Последнее редактирование:

FYP

Известный
Автор темы
Администратор
1,758
5,726
Помогите.
Только начал разбираться в LUA, не понимаю в чем ошибка.

Lua:
smsnick, smsnomer, smstext = string.match(text, "(%a+_%a+).(%d+).(.+)")

Даже через
Lua:
if string.find(

ищу нужное мне слово, но ничего не находится.

Знаю, что ошибка в первой строке, но как исправить не знаю, может кто поможет.

В игре в чате выводит так: %s[%d]: %s (ник, ид, текст)
string.match(text, "(%a+_%a+)%[(%d+)%]: (.+)") правильнее будет, но твой вариант тоже рабочий
 

itsLegend

Фонд борьбы за жуков 🐞
Администратор
2,696
1,460
Скачал raksamp, в файле netrpc.cpp нашел этот код (мне нужно отловить вывод TextDraw):
C++:
void ScrShowTextDraw(RPCParameters *rpcParams)
{
    PCHAR Data = reinterpret_cast<PCHAR>(rpcParams->input);
    int iBitLength = rpcParams->numberOfBitsOfData;

    RakNet::BitStream bsData((unsigned char *)Data,(iBitLength/8)+1,false);

    WORD wTextID;
    TEXT_DRAW_TRANSMIT TextDrawTransmit;

    CHAR cText[1024];
    unsigned short cTextLen = 0;

    bsData.Read(wTextID);
    bsData.Read((PCHAR)&TextDrawTransmit, sizeof(TEXT_DRAW_TRANSMIT));
    bsData.Read(cTextLen);
    bsData.Read(cText, cTextLen);
    cText[cTextLen] = '\0';

    if(settings.uiTextDrawsLogging != 0)
        SaveTextDrawData(wTextID, &TextDrawTransmit, cText);
 
    if(TextDrawTransmit.byteSelectable)
        Log("[SELECTABLE-TEXTDRAW] ID: %d, Text: %s.", wTextID, cText);
}
Как теперь определить, какие параметры используются в событии? Здесь все в куче, ничего не понятно.
  • WORD wTextID
  • TEXT_DRAW_TRANSMIT - структура, в раксампе так же найди; по порядку как и в структуре читается
  • unsigned short cTextLen
  • CHAR cText[1024]
 

Roman13371

Новичок
6
2
Вопрос, создаю автоответчик на "смс".
Вроде все получается, но есть одна проблема, на вопрос идёт флуд, который не останавливается.
Если пишу во время этого флуда любое сообщение в чат, скрипт крашится с ошибкой "0A0C1194" или же иногда: "01AC587C"

ЛОГ:

[23:40:32.309000] (error) Неизвестно: ...rogram Files\San Andreas Multiplayer\moonloader\asms.lua:49: bad argument #1 to 'find' (string expected, got nil)
[23:40:32.337000] (error) Неизвестно: Script died due to error. (0A0C1194)

КОД:

Lua:
function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("asms", autootvetsms)
    repeat
    wait(0)
    until sampIsLocalPlayerSpawned()
    while true do
    wait(1000)
        -- Автоответчик на смс
        if SMSGO == true then
            sampSendChat(string.format("/sms %d Привет", smsnomer))
             SMSGO = false
        end
    end
end

Lua:
function sampev.onServerMessage(color, text)
    if pSMS == 1 then
            smsnick, smsnomer, smstext = string.match(text, "(%a+_%a+)%[(%d+)%](.+)")
              if string.find(smstext, "Привет") then
                   SMSGO = true
                end
    end
end
 
Последнее редактирование:

Garrus

Известный
159
20
Вопрос, создаю автоответчик на "смс".
Вроде все получается, но есть одна проблема, на вопрос идёт флуд, который не останавливается.
Если пишу во время этого флуда любое сообщение в чат, скрипт крашится с ошибкой "0A0C1194".

ЛОГ:

[23:40:32.309000] (error) Неизвестно: ...rogram Files\San Andreas Multiplayer\moonloader\asms.lua:49: bad argument #1 to 'find' (string expected, got nil)
[23:40:32.337000] (error) Неизвестно: Script died due to error. (0A0C1194)

КОД:

Lua:
function main()
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand("asms", autootvetsms)
    repeat
    wait(0)
    until sampIsLocalPlayerSpawned()
    while true do
    wait(1000)
        -- Автоответчик на смс
        if SMSGO == true then
            sampSendChat(string.format("/sms %d Привет", smsnomer))
             SMSGO = false
        end
    end
end

Lua:
function sampev.onServerMessage(color, text)
    if pSMS == 1 then
            smsnick, smsnomer, smstext = string.match(text, "(%a+_%a+)%[(%d+)%](.+)")
              if string.find(smstext, "Привет") then
                   SMSGO = true
                end
    end
end
Попробуй так)
Код:
function sampev.onServerMessage(color, text)
    if pSMS == 1 then
            smsnick, smsnomer, smstext = string.match(text, "(%a+_%a+)%[(%d+)%](.+)")
              if smstext ~= nil
                   then
              if string.find(smstext, "Привет") then
                   SMSGO = true
                end
                  end
end
end
 

Roman13371

Новичок
6
2
Попробуй так)
Код:
function sampev.onServerMessage(color, text)
    if pSMS == 1 then
            smsnick, smsnomer, smstext = string.match(text, "(%a+_%a+)%[(%d+)%](.+)")
              if smstext ~= nil
                   then
              if string.find(smstext, "Привет") then
                   SMSGO = true
                end
                  end
end
end

все равно флудит и теперь выдает ошибку "01993EEC"
 
Последнее редактирование:

Bogach

Активный
558
27
все равно флудит и теперь выдает ошибку "01993EEC"
Я же тебе показывал как правильно сделать.
1. Не нужно было убирать проверку переменных на nil.
if smsnick ~= nil and smsnomer ~= nil and smstext ~= nil then
В ней уже делай условие на слова в сообщении SMS
end

Смотри как в теме я сделал, в предпоследнем сообщении: https://www.blast.hk/threads/15953/
 

winrare

Новичок
75
1
  • WORD wTextID
  • TEXT_DRAW_TRANSMIT - структура, в раксампе так же найди; по порядку как и в структуре читается
  • unsigned short cTextLen
  • CHAR cText[1024]
Сделал так:
Lua:
local sampev = require 'lib.samp.events'
local raknet = require 'lib.samp.raknet'
sampev.INTERFACE.INCOMING_RPCS[raknet.RPC.SHOWTEXTDRAW] = {'onShowTextDraw', {textDrawID = 'int32'}, {data = 'TEXT_DRAW_TRANSMIT'}, {textLen = 'int32'}, {text = 'string32'}}
Выдает ошибку:
\lib\samp\events_core.lua:35: attempt to index a nil value

Очевидно SAMP.lua не знает тип TEXT_DRAW_TRANSMIT. Как ему рассказать про него?
 

MISTER_GONWIK

Всефорумный гонщик
Всефорумный модератор
1,260
1,740
Сделал так:
Lua:
local sampev = require 'lib.samp.events'
local raknet = require 'lib.samp.raknet'
sampev.INTERFACE.INCOMING_RPCS[raknet.RPC.SHOWTEXTDRAW] = {'onShowTextDraw', {textDrawID = 'int32'}, {data = 'TEXT_DRAW_TRANSMIT'}, {textLen = 'int32'}, {text = 'string32'}}
Выдает ошибку:
\lib\samp\events_core.lua:35: attempt to index a nil value

Очевидно SAMP.lua не знает тип TEXT_DRAW_TRANSMIT. Как ему рассказать про него?
тебе русским языком написали, что это структура
 

FYP

Известный
Автор темы
Администратор
1,758
5,726
@Roman13371 флудит потому что зацикливается, т.к. и твои сообщения обрабатываются через onServerMessage. нужно фильтровать свои сообщения.
"0A0C1194", "01AC587C" и т.п. это не код ошибки, а указатель на скрипт. вообще не обращай на них внимание.
И что, мне теперь каждый тип из этой структуры по отдельности вписывать надо?
ну да, либо юзануть ffi.
 

Bogach

Активный
558
27
А можно ли как - то сделать,чтобы не показывало какие - то сообщения, приведу пример.
При выдаче скина автовыдачей, пишет нам какой скин выдали и кому, если игроком пишет много - флуд, можно ли как - то сделать так, чтобы данное сообщение не выводилось?
 

winrare

Новичок
75
1
Возможно не в той теме спрашиваю.
Как написать бота, который будет работать без запуска GTA? Есть какие-то готовые средства?