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

k1sher

Известный
201
4
Поможете поправить скрипт?

Код:
require 'lib.moonloader'

local key = VK_E

function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    while true do
        wait(0)
     local result, target = getCharPlayerIsTargeting(playerHandle)
        if result then result, playerid = sampGetPlayerIdByCharHandle(target)
            level = sampGetPlayerScore(playerid)
        if isKeyDown(VK_MENU) and isKeyJustPressed(VK_1) then
            mycolor = sampGetPlayerColor(PLAYER_PED)
                    if level <= 1 then
                        price = 5000
                    end
                    if level > 1 and level <= 4 then
                        price = 8000
                    end
                    if level > 4 and level <= 9 then
                        price = 12000
                    end
                    if level > 9 and level <= 24 then
                        price = 15000
                    end
                    if level > 24 then
                        price = 20000
                    end
                                    if mycolor == 3851630847 then
                    sampSendChat("/c price = %d .. color = %d", price, mycolor)
                    else
                        sampAddChatMessage("{FC5A03}У тебя не включен цвет!", 0xFFFFFF)
                end   
            end
        end
    end
end

Что же в нем не так?(
 

romacaddy

Известный
Проверенный
234
206
mycolor = sampGetPlayerColor(PLAYER_PED)
надо со своего ида цвет получать, а не с хендла
Lua:
local _, myId = sampGetPlayerIdByCharHandle(PLAYER_PED)
local myColor = sampGetPlayerColor(myId)
sampSendChat("/c price = %d .. color = %d", price, mycolor)
Lua:
sampSendChat(string.format('/c price = %d .. color = %d', price, mycolor))
 
  • Нравится
Реакции: k1sher

k1sher

Известный
201
4
Почему так?
Код:
require 'lib.moonloader'

local key = VK_E

function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    while true do
        wait(0)
            local _, myId = sampGetPlayerIdByCharHandle(PLAYER_PED)
            local myColor = sampGetPlayerColor(myId)  
         if isKeyDown(VK_MENU) and isKeyJustPressed(VK_1) then
                       sampAddChatMessage(string.format("%d", mycolor), mycolor)          
            end
        end
    end
Лог ошибка = lua:13: bad argument #2 to 'format' (number expected, got nil)
 

memir

🇷🇺
Всефорумный модератор
333
597
Почему так?
Код:
require 'lib.moonloader'

local key = VK_E

function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    while not isSampAvailable() do wait(100) end
    while true do
        wait(0)
            local _, myId = sampGetPlayerIdByCharHandle(PLAYER_PED)
            local myColor = sampGetPlayerColor(myId)
         if isKeyDown(VK_MENU) and isKeyJustPressed(VK_1) then
                       sampAddChatMessage(string.format("%d", mycolor), mycolor)      
            end
        end
    end
Лог ошибка = lua:13: bad argument #2 to 'format' (number expected, got nil)
Код:
sampAddChatMessage(string.format("%d", myColor), myColor)
вместо
Код:
sampAddChatMessage(string.format("%d", mycolor), mycolor)
Lua - регистрозависимый язык
 
  • Нравится
Реакции: k1sher

k1sher

Известный
201
4
Подскажите пожалуйста, как можно засечь таймер например 500 секунд и вывести его на экран с помощью renderFontDrawText
 
Последнее редактирование:

egor230

Участник
47
16
Стал очень интересен moonloader как хорошая альтернатива cleo в будущим.
По cleo очень много уроков, статей, особенно, по gta sa. Выучить можно при желании азы.
Раньше написал несколько десяток сриптов на cleo.
Попробовал на lua, дать cj оружие, не получилось.
Где ж моя ошибка, Скажите, пожалуйста, моя ошибка, очень хочу научиться.
Код:
script_author("egor")
script_name("weapon")
require "lib.moonloader"

function main()
while true do
requestModel(346 )
  wait(10)
  if isKeyDown(VK_1) and isPlayerPlaying(playerHandle) then
    GiveWeaponToChar(playerHandle, 346, 100)
end
 
1,417
1,029
Стал очень интересен moonloader как хорошая альтернатива cleo в будущим.
По cleo очень много уроков, статей, особенно, по gta sa. Выучить можно при желании азы.
Раньше написал несколько десяток сриптов на cleo.
Попробовал на lua, дать cj оружие, не получилось.
Где ж моя ошибка, Скажите, пожалуйста, моя ошибка, очень хочу научиться.
Код:
script_author("egor")
script_name("weapon")
require "lib.moonloader"

function main()
while true do
requestModel(346 )
  wait(10)
  if isKeyDown(VK_1) and isPlayerPlaying(playerHandle) then
    GiveWeaponToChar(playerHandle, 346, 100)
end
в giveweapon вместо playerhandle надо PLAYER_PED
 

inf

Известный
77
89
Подскажите пожалуйста, как можно засечь таймер например 500 секунд и вывести его на экран с помощью renderFontDrawText
Lua:
require 'lib.moonloader'
require 'lib.sampfuncs'

local font = nil
local waitto = 0

function main()
    if not isSampLoaded() or not isCleoLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    font = renderCreateFont("Tahoma", 14, FCR_BORDER)
    waitto = os.clock() + 500.0

    while true do
        if waitto < os.clock() then waitto = os.clock() + 500.0 end
        local w, h = getScreenResolution()
        renderFontDrawText(font, string.format('%.1f', waitto-os.clock()), w/2, h/2, 0xffffffff)
        wait(1)
    end
end

function onExitScript()
    if font then renderReleaseTexture(font) end
end
 
  • Нравится
Реакции: k1sher

k1sher

Известный
201
4
Lua:
require 'lib.moonloader'
require 'lib.sampfuncs'

local font = nil
local waitto = 0

function main()
    if not isSampLoaded() or not isCleoLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    font = renderCreateFont("Tahoma", 14, FCR_BORDER)
    waitto = os.clock() + 500.0

    while true do
        if waitto < os.clock() then waitto = os.clock() + 500.0 end
        local w, h = getScreenResolution()
        renderFontDrawText(font, string.format('%.1f', waitto-os.clock()), w/2, h/2, 0xffffffff)
        wait(1)
    end
end

function onExitScript()
    if font then renderReleaseTexture(font) end
end

Спасибо больше, а как тут можно сделать не секунды/миллисекунды, а минуты/секунды?
 

inf

Известный
77
89
Спасибо больше, а как тут можно сделать не секунды/миллисекунды, а минуты/секунды?
Lua:
require 'lib.moonloader'
require 'lib.sampfuncs'

local font = nil
local waitto = 0

function main()
    if not isSampLoaded() or not isCleoLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    font = renderCreateFont("Tahoma", 14, FCR_BORDER)
    waitto = os.clock() + 15.0

    while true do
        if waitto < os.clock() then waitto = os.clock() + 500.0 end
        local w, h = getScreenResolution()
        local time = waitto-os.clock()
        local minutes = math.floor(time/60)
        local secs = math.fmod(time, 60)
        renderFontDrawText(font, string.format('%d m %02d s', minutes, secs), w/2, h/2, 0xffffffff)
        wait(1)
    end
end

function onExitScript()
    if font then renderReleaseTexture(font) end
end
 
  • Нравится
Реакции: 4el0ve4ik и k1sher

egor230

Участник
47
16
neket5k,
Спасибо большое уважаемый neket5k за Ваш ответ.
Поймите меня правильно, moonloader для многих темным лес. Чем больше людей будут на нем писать, тем быстрее он будет развиваться.
Сейчас людям нужно понять азы, чтобы завоевать популярность.
Понимаю, что мои вопросы простые для профессиональных программистов, они помогут людям перестать быть нубам.
Решил добавит вывод надпись printString ("GiveWeapon", 3000) -- надпись дано оружие, чтобы отследить работу скрипт.
Пока скрипт не работает, мучаюсь как "Рыба об лед".

Код:
script_author("egor")
script_name("weapon")
require "lib.moonloader"

function main()
while true do
wait(0)
if isPlayerPlaying (PLAYER_PED) then 
    if isKeyDown(VK_1)  then
     printString ("GiveWeapon", 3000) -- надпись дано оружие
requestModel(362)
    GiveWeaponToChar(PLAYER_PED, 362, 100)
end
end
end
end
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
@egor230 PLAYER_PED = $PLAYER_ACTOR, PLAYER_HANDLE = $PLAYER_CHAR в клео, функция isPlayerPlaying принимает хендл игрока, а не персонажа, соответственно, в неё нужно передавать PLAYER_HANDLE.
луа - регистрозависимый язык, так что вместо GiveWeaponToChar должно быть giveWeaponToChar. и эта функция принимает ид оружия, а не ид модели.
 

egor230

Участник
47
16
FYP, Большое спасибо Вам за Ваше очень подробное объяснение. Оно помогло не только мне, но и многим другим новичкам.
Все работает хорошо, но есть один баг, может дать оружие, прежде чем модель загрузилась, чтобы это исправить, в cleo используем опкод 0248: model 15@ available в lua его аналогом выступает hasModelLoaded.
К сожалению не знаю как его правильно использовать.
Не сочтите за наглость, очень хочу разобраться, помогите, пожалуйста.
HTML:
script_author("egor")
script_name("weapon")
require "lib.moonloader"

function main() -- объявление функции
while true do -- бесконечный цикл
wait(0) -- задержка в 0 мс
if isPlayerPlaying (PLAYER_HANDLE) then  -- если игрок найден
    if isKeyDown(VK_1)  then -- если клавиша 1 нажата
    requestModel(362) -- запрос модели минигана
    if hasModelLoaded(362 38) then -- проверить загружена модель и ее id
while isKeyDown(VK_1) do wait(100) end -- и ждём, пока клавиша не будет отпущена  
   printString ("GiveWeapon", 1000) -- надпись дано оружие, второй параметр время надписи
    giveWeaponToChar(PLAYER_PED, 38, 100) -- дать миниган
    markModelAsNoLongerNeeded (362, 38) -- удалить модель и id из памяти
end
end
end
end
end
 

FYP

Известный
Автор темы
Администратор
1,758
5,722
@egor230 точно так же, как и в клео. циклично проверять, загрузилась ли модель:
Lua:
while not hasModelLoaded(362) do  -- ждём, пока модель не загрузится
  wait(0)
end
вместо этого можно воспользоваться функцией
Lua:
function load_model(model)
  if not hasModelLoaded(model) then
    requestModel(model)
    loadAllModelsNow()
    while not hasModelLoaded(model) do wait(0) end
  end
end
она и загружает модель, и ожидает, пока модель загрузится.
вызов: load_model(362).

у тебя в коде есть ошибки, советую почаще заглядывать в лог moonloader.log и на wiki