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

tlwsn

Известный
537
85
Lua:
function ftext(name)
sampAddChatMessage(" "..name, 0xAAAAAAAA)
end
function starttp()
    lua_thread.create(function()
        sborid = not sborid
        ftext(sborid and 'Сбор ID начат.' or 'Сбор ID окончен')
        while sborid do wait(0) end
        sampSendChat('/togphone')
        wait(1200)
        for i, v in pairs(tpids) do
            sampSendChat('/gethere '..v)
            table.remove(tpids, i)
            wait(1200)
        end
        ftext('Готово')
    end)
end
почему оно все ниже чем
Lua:
выполняет по два раза?
 
Последнее редактирование:

CatKnight

Известный
148
55
я всё вроде бы начал, только не могу сделать чек финда
Отправляешь на сервер команду find через sampSendChat("/find"), присваиваешь какой-то переменной значение true. Через события отслеживаешь нужный диалог и оттуда берёшь информацию, затем "убиваешь" rpc. Ниже примерный код. Пробуй, экспериментируй.

Lua:
-- до main
local res, sampev = pcall(require, 'lib.samp.events')
assert(res, 'Library SAMP Events not found')
local enable = false

-- где-то в коде
enable = true
sampSendChat("/find")
-- где-то после main
function sampev.onShowDialog(dialogid, style, caption, button1, button2, text)
    if enable and caption:find("Онлайн организации") then -- инф-ю по диалогу сам ищи
        enable = false
        -- действия с текстом
        return false -- чтобы не выводился на экран
    end;
end
 
  • Нравится
Реакции: ZaNki222

ZaNki222

Известный
24
1
Отправляешь на сервер команду find через sampSendChat("/find"), присваиваешь какой-то переменной значение true. Через события отслеживаешь нужный диалог и оттуда берёшь информацию, затем "убиваешь" rpc. Ниже примерный код. Пробуй, экспериментируй.

Lua:
-- до main
local res, sampev = pcall(require, 'lib.samp.events')
assert(res, 'Library SAMP Events not found')
local enable = false

-- где-то в коде
enable = true
sampSendChat("/find")
-- где-то после main
function sampev.onShowDialog(dialogid, style, caption, button1, button2, text)
    if enable and caption:find("Онлайн организации") then -- инф-ю по диалогу сам ищи
        enable = false
        -- действия с текстом
        return false -- чтобы не выводился на экран
    end;
end
хорошо, спасибо большое, а как это показать в сообщение в чат?
 

CatKnight

Известный
148
55
хорошо, спасибо большое, а как это показать в сообщение в чат?
После нужный действий с полученной информацией выводишь через sampSendChat("/f " .. text)

Lua:
function ftext(name)
sampAddChatMessage(" "..name, 0xAAAAAAAA)
end
function starttp()
    lua_thread.create(function()
        sborid = not sborid
        ftext(sborid and 'Сбор ID начат.' or 'Сбор ID окончен')
        while sborid do wait(0) end
        sampSendChat('/togphone')
        wait(1200)
        for i, v in pairs(tpids) do
            sampSendChat('/gethere '..v)
            table.remove(tpids, i)
            wait(1200)
        end
        ftext('Готово')
    end)
end
почему оно все ниже чем
Lua:
выполняет по два раза?
Потому что когда ты вводишь в первый раз, вечный цикл стопорится и ждет, пока переменная sborid станет ложной. Ты вводишь второй раз, и у тебя в двух потоках выполняются действия.
Если ты хочешь сделать возможность досрочно останавливать выполнение сбора после очередного ввода команды, то вариант с wait(1200) тебе не подходит. Нужно в беск цикле при помощи таймера делать задержки и делать все действия, чтобы цикл постоянно прокручивался, например каждый кадр, иначе проверок тебе не сделать.
 
  • Нравится
Реакции: tlwsn

CatKnight

Известный
148
55

tlwsn

Известный
537
85
есть массив:
Lua:
local gostp = {
    ['LSPD'] = '1544.1212158203, -1675.3117675781, 13.557789802551',
    ['SFPD'] = '-1606.0246582031, 719.93884277344, 12.054424285889',
    ['LVPD'] = '2333.9365234375, 2455.9772949219, 14.96875',
    ['FBI'] = '-2444.9887695313, 502.21490478516, 30.094774246216',
    ['Мэрия'] = '1478.6057128906, -1738.2475585938, 13.546875',
    ['Автошкола'] = '-2032.9953613281, -84.548896789551, 35.82837677002',
    ['Больница ЛС'] = '1188.3579101563, -1322.6630859375, 13.566570281982',
    ['Больница СФ'] = '-2664.5402832031, 634.74700927734, 14.453125',
    ['Больница ЛВ'] = '1606.6192626953, 1825.5887451172, 10.8203125'
}
. Как сделать, что бы оно было в таком же порядке а не в разброс
 

CatKnight

Известный
148
55
есть массив:
Lua:
local gostp = {
    ['LSPD'] = '1544.1212158203, -1675.3117675781, 13.557789802551',
    ['SFPD'] = '-1606.0246582031, 719.93884277344, 12.054424285889',
    ['LVPD'] = '2333.9365234375, 2455.9772949219, 14.96875',
    ['FBI'] = '-2444.9887695313, 502.21490478516, 30.094774246216',
    ['Мэрия'] = '1478.6057128906, -1738.2475585938, 13.546875',
    ['Автошкола'] = '-2032.9953613281, -84.548896789551, 35.82837677002',
    ['Больница ЛС'] = '1188.3579101563, -1322.6630859375, 13.566570281982',
    ['Больница СФ'] = '-2664.5402832031, 634.74700927734, 14.453125',
    ['Больница ЛВ'] = '1606.6192626953, 1825.5887451172, 10.8203125'
}
. Как сделать, что бы оно было в таком же порядке а не в разброс
Мне сходу пришло два варианта.
Либо в индексах вместо названий орг написать числовые значения и прогонять при выводе через цикл. Либо сделать отдельную таблицу с названиями индексов, потом при выводе сделать цикл по этой таблице и значение каждого элемента подставлять в индекс другой таблицы как переменную при выводе. Если не понял, и не придумаешь ничего , завтра опишу
 

ШPEK

Известный
1,474
525
В каких случаях работает loadAudioStream(zstring audio) и setAudioStreamState(AudioStream handle, int state)?
Она то работает, то нет (как я заметил, музыка проигрывается если зайти в игру с определёнными настройками*).
*определённые настройки - включенный звук в игре (radio)

UPD: Ещё одна закономерность, если зайти в игру без включенных звуков, а после чего включить звуки она работать не будет, но если вдруг сервер проиграет какой-то звук (к примеру серверное радио), то функция заработает
local sound = loadAudioStream("moonloader/music.mp3")
setAudioStreamVolume(sound, 10)
setAudioStreamState(sound, 1)
Когда начал устанавливать звук - всё начало работать

есть массив:
Lua:
local gostp = {
    ['LSPD'] = '1544.1212158203, -1675.3117675781, 13.557789802551',
    ['SFPD'] = '-1606.0246582031, 719.93884277344, 12.054424285889',
    ['LVPD'] = '2333.9365234375, 2455.9772949219, 14.96875',
    ['FBI'] = '-2444.9887695313, 502.21490478516, 30.094774246216',
    ['Мэрия'] = '1478.6057128906, -1738.2475585938, 13.546875',
    ['Автошкола'] = '-2032.9953613281, -84.548896789551, 35.82837677002',
    ['Больница ЛС'] = '1188.3579101563, -1322.6630859375, 13.566570281982',
    ['Больница СФ'] = '-2664.5402832031, 634.74700927734, 14.453125',
    ['Больница ЛВ'] = '1606.6192626953, 1825.5887451172, 10.8203125'
}
. Как сделать, что бы оно было в таком же порядке а не в разброс
Обозначить значения цифрами или вообще не писать индекс тогда у значений будет ключ
 

Шурик

Активный
216
43
local sound = loadAudioStream("moonloader/music.mp3")
setAudioStreamVolume(sound, 10)
setAudioStreamState(sound, 1)
Когда начал устанавливать звук - всё начало работать
Повторюсь:
Она то работает, то нет (как я заметил, музыка проигрывается если зайти в игру с определёнными настройками*).
*определённые настройки - включенный звук в игре (radio)

UPD: Ещё одна закономерность, если зайти в игру без включенных звуков, а после чего включить звуки она работать не будет, но если вдруг сервер проиграет какой-то звук (к примеру серверное радио), то функция заработает
Как сделать, чтобы такого не было?

UPD: Возможно это поможет:
В АХК есть следующие функции, может они смогут помочь? (если не сложно, помогите перевести на lua)
Код:
patchRadio()
{
    if(!checkHandles())
        return false
   
    VarSetCapacity(nop, 4, 0)
    NumPut(0x90909090,nop,0,"UInt")
   
    dwFunc := dwSAMP + FUNC_SAMP_PLAYAUDIOSTR
    writeRaw(hGTA, dwFunc, &nop, 4)
    writeRaw(hGTA, dwFunc+4, &nop, 1)
   
    dwFunc := dwSAMP + FUNC_SAMP_STOPAUDIOSTR
    writeRaw(hGTA, dwFunc, &nop, 4)
    writeRaw(hGTA, dwFunc+4, &nop, 1)
    return true
}

unPatchRadio()
{
    if(!checkHandles())
        return false
   
    VarSetCapacity(old, 4, 0)
   
    dwFunc := dwSAMP + FUNC_SAMP_PLAYAUDIOSTR
    NumPut(0x74003980,old,0,"UInt")
    writeRaw(hGTA, dwFunc, &old, 4)
    NumPut(0x39,old,0,"UChar")
    writeRaw(hGTA, dwFunc+4, &old, 1)
   
    dwFunc := dwSAMP + FUNC_SAMP_STOPAUDIOSTR
    NumPut(0x74003980,old,0,"UInt")
    writeRaw(hGTA, dwFunc, &old, 4)
    NumPut(0x09,old,0,"UChar")
    writeRaw(hGTA, dwFunc+4, &old, 1)
    return true
}
 
Последнее редактирование:

seruj22048

Участник
74
6
Как ввести ответ в диалог? Пробовал через
sampSendDialogResponse(dialogid, 1, 0, "4")
sampCloseCurrentDialogWithButton(0)
Но в таком случае диалог пропадает, но не работают пикапы
 

madrasso

Потрачен
883
325
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Может ли крашить из за постоянного использования цикла for?