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

imring

Ride the Lightning
Всефорумный модератор
2,362
2,545
Как иероглефы перевести в русские после смены кодировки?
ПЕРЕПИСЫВАТЬ ЗАНОВО ЛУЧШЕ ВООБЩЕ ЗАБРОСИТЬ(((
там много
сделай кодировку utf-8, скопируй весь текст. потом верни старую кодировку и вставь текст
 

AnWu

https://t.me/anwublog
Всефорумный модератор
4,760
5,367
Lua:
void CalcScreenCoors(D3DXVECTOR3 *vecWorld, D3DXVECTOR3 *vecScreen) {
     D3DXMATRIX    m((float *)(0xB6FA2C));
     DWORD        *dwLenX = (DWORD *)(0xC17044);
     DWORD        *dwLenY = (DWORD *)(0xC17048);
     vecScreen->x = (vecWorld->z * m._31) + (vecWorld->y * m._21) + (vecWorld->x * m._11) + m._41;
     vecScreen->y = (vecWorld->z * m._32) + (vecWorld->y * m._22) + (vecWorld->x * m._12) + m._42;
     vecScreen->z = (vecWorld->z * m._33) + (vecWorld->y * m._23) + (vecWorld->x * m._13) + m._43;
     double    fRecip = (double)1.0 / vecScreen->z;
     vecScreen->x *= (float)(fRecip * (*dwLenX));
     vecScreen->y *= (float)(fRecip * (*dwLenY));
}
Есть аналог на луа? Мозгов немного не хватает чтобы перевести на луа. Не шарю в cpp
 
Последнее редактирование:

RTD

Потужно
Модератор
399
470
Lua:
void CalcScreenCoors(D3DXVECTOR3 *vecWorld, D3DXVECTOR3 *vecScreen) {
     D3DXMATRIX    m((float *)(0xB6FA2C));
     DWORD        *dwLenX = (DWORD *)(0xC17044);
     DWORD        *dwLenY = (DWORD *)(0xC17048);
     vecScreen->x = (vecWorld->z * m._31) + (vecWorld->y * m._21) + (vecWorld->x * m._11) + m._41;
     vecScreen->y = (vecWorld->z * m._32) + (vecWorld->y * m._22) + (vecWorld->x * m._12) + m._42;
     vecScreen->z = (vecWorld->z * m._33) + (vecWorld->y * m._23) + (vecWorld->x * m._13) + m._43;
     double    fRecip = (double)1.0 / vecScreen->z;
     vecScreen->x *= (float)(fRecip * (*dwLenX));
     vecScreen->y *= (float)(fRecip * (*dwLenY));
}
Есть аналог на луа? Мозгов немного не хватает чтобы перевести на луа. Не шарю в cpp
Переведи тогда с АХК. В SAMP-UDF вроде это есть.
 

4el0ve4ik

Известный
Всефорумный модератор
1,550
1,343
Lua:
void CalcScreenCoors(D3DXVECTOR3 *vecWorld, D3DXVECTOR3 *vecScreen) {
     D3DXMATRIX    m((float *)(0xB6FA2C));
     DWORD        *dwLenX = (DWORD *)(0xC17044);
     DWORD        *dwLenY = (DWORD *)(0xC17048);
     vecScreen->x = (vecWorld->z * m._31) + (vecWorld->y * m._21) + (vecWorld->x * m._11) + m._41;
     vecScreen->y = (vecWorld->z * m._32) + (vecWorld->y * m._22) + (vecWorld->x * m._12) + m._42;
     vecScreen->z = (vecWorld->z * m._33) + (vecWorld->y * m._23) + (vecWorld->x * m._13) + m._43;
     double    fRecip = (double)1.0 / vecScreen->z;
     vecScreen->x *= (float)(fRecip * (*dwLenX));
     vecScreen->y *= (float)(fRecip * (*dwLenY));
}
Есть аналог на луа? Мозгов немного не хватает чтобы перевести на луа. Не шарю в cpp
Lua:
    float wposX, float wposY = convert3DCoordsToScreen(float posX, float posY, float posZ)
Оно, не?
 

Hatiko

Известный
Проверенный
1,494
617
Помогите разобраться с проблемой. После танцем с бубном начало выдавать в место ошибки другие данные, а именно [ML] (script) test.lua: table: 0x10152dd8
Lua:
    if imgui.Button("Главное", imgui.ImVec2(130, 20)) then
        for i = 0, sampGetMaxPlayerId(true) do
        local result, handle = sampGetCharHandleBySampPlayerId(i)
            if result and doesCharExist(handle) then
            pls = {}
            table.insert(pls, i)
            end
            end
            print{sampGetPlayerNickname(pls[i])}
            end
[code]

Частично, так скажем, работает, выдаёт те строчки = количеству игроков
 
Последнее редактирование:

AnWu

https://t.me/anwublog
Всефорумный модератор
4,760
5,367
Lua:
    float wposX, float wposY = convert3DCoordsToScreen(float posX, float posY, float posZ)
Оно, не?
Не. Я её использую, и она работает немного не так. Она не возвращает вектор, а он нужен мне. X, Y, Z и когда рисую линию, и отвернусь от коордов, то линия ведет себя неадекватно, прям пзц как.

@Boris Yeltsin
Lua:
function calcScreenCoors(fX,fY,fZ)
    local dwM = 0xB6FA2C
    dwM = sampGetBase() + dwM
   
    local m_11 = memory.getfloat(dwM + 0*4)
    local m_12 = memory.getfloat(dwM + 1*4)
    local m_13 = memory.getfloat(dwM + 2*4)
    local m_21 = memory.getfloat(dwM + 4*4)
    local m_22 = memory.getfloat(dwM + 5*4)
    local m_23 = memory.getfloat(dwM + 6*4)
    local m_31 = memory.getfloat(dwM + 8*4)
    local m_32 = memory.getfloat(dwM + 9*4)
    local m_33 = memory.getfloat(dwM + 10*4)
    local m_41 = memory.getfloat(dwM + 12*4)
    local m_42 = memory.getfloat(dwM + 13*4)
    local m_43 = memory.getfloat(dwM + 14*4)
   
    local dwLenX = memory.getint32(sampGetBase() + 0xC17044)
    local dwLenY = memory.getint32(sampGetBase() + 0xC17048)
   
    frX = fZ * m_31 + fY * m_21 + fX * m_11 + m_41
    frY = fZ * m_32 + fY * m_22 + fX * m_12 + m_42
    frZ = fZ * m_33 + fY * m_23 + fX * m_13 + m_43
   
    fRecip = 1.0/frZ
    frX = frX * (fRecip * dwLenX)
    frY = frY * (fRecip * dwLenY)
   
    if(frX<=dwLenX and frY<=dwLenY and frZ>1)then
        return frX, frY, frZ
    else
        return -1, -1, -1
    end
end
Всегда возвращает -1, -1, -1
 
Последнее редактирование модератором:

Vlad Horii

Известный
Проверенный
310
172
Вопрос:
Как сделать проверку, что сообщение отправил сервер, а не игрок?
(Сообщение из чата буду ловить хуком)
 

uczoja62

Новичок
74
4
Вопрос:
Как сделать проверку, что сообщение отправил сервер, а не игрок?
(Сообщение из чата буду ловить хуком)
Какие-нибудь символы из регулярок, которые могут исключить ники игроков, например? Совпадение строго в начале/конце строки: ^, $.

Продолжает ли сервер считать, что у меня открыт диалог, если я его скрыл через return false? Нужно ли отправлять sampCloseCurrentDialogWithButton с точки зрения сервера, или это необходимо только для того, чтобы на экране не было самого диалога лично у тебя?
 

AnWu

https://t.me/anwublog
Всефорумный модератор
4,760
5,367
Вопрос:
Как сделать проверку, что сообщение отправил сервер, а не игрок?
(Сообщение из чата буду ловить хуком)
смысле? onServerMessage только серверные ловит.

Какие-нибудь символы из регулярок, которые могут исключить ники игроков, например? Совпадение строго в начале/конце строки: ^, $.

Продолжает ли сервер считать, что у меня открыт диалог, если я его скрыл через return false? Нужно ли отправлять sampCloseCurrentDialogWithButton с точки зрения сервера, или это необходимо только для того, чтобы на экране не было самого диалога лично у тебя?
сервер принимает Респонз. Ему плевать открыт ли у тебя дилог или нет.
 
Последнее редактирование модератором:

uczoja62

Новичок
74
4
сервер принимает Респонз. Ему плевать открыт ли у тебя дилог или нет.
Тогда я мог бы отправить, например, sampSendDialogResponse(5, 1, 0, "Статистика") и сразу попасть в диалог статистики, минуя предыдущие два диалога, но этого не происходит - ноль реакции. А вот если открыть начальный диалог командой - работает. Может ли это быть спецификой сервера?
 
Последнее редактирование:

ZKelo

Известный
82
25
В скрипте есть цикл для перебора массива с никами игроков. Внутри этого цикла есть ещё один цикл, который проходится по ID игроков, начиная с 0 и заканчивая максимальным ID, получаемым от функции sampGetMaxPlayerId.

В процессе работы скрипта возникает следующая ошибка.
Код:
[ML] (error) MyScript: ...Theft Auto San Andreas\moonloader\MyScript.lua:687: attempt to call a number value
stack traceback:
    ...Theft Auto San Andreas\moonloader\MyScript.lua:687: in function <...Theft Auto San Andreas\moonloader\MyScript.lua:665>
[ML] (error) MyScript: Script died due to error. (0B0DA83C)

Вот код этого цикла.
Lua:
for index, value in ipairs(nicknameArray) do
    local onlineStatus = "Оффлайн"
    local playerId
    local maxPlayerId = sampGetMaxPlayerId(false)
    for playerId in 0, maxPlayerId do -- 687 строка
        if sampIsPlayerConnected(playerId) then
            if sampGetPlayerNickname(playerId) == value.nickname then
                onlineStatus = "Онлайн"
            end
        end
    end
end

В чём здесь ошибка?
 
Последнее редактирование:

AnWu

https://t.me/anwublog
Всефорумный модератор
4,760
5,367
Тогда я мог бы отправить, например, sampSendDialogResponse(5, 1, 0, "Статистика") и сразу попасть в диалог статистики, минуя предыдущие два диалога, но этого не происходит - ноль реакции. А вот если открыть начальный диалог командой - работает. Может ли это быть спецификой сервера?
да. чере переменные проверки сделали.