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

Drey4ik

Новичок
3
0
Я сделал бы по другому:
1. Создать новые собственные команды (/in [id] [rang], 1-ый арг обязательно, 2-ой нет. если только ид, то отыграется без рп на изменение ранга)
1.1. Затем создать поток на инвайт игрока с рп. (без ранга)
2. Прохукать на чат на изменение после конкретного инвайта
2.1. Если совпадает условиями как и вы принимали, следовать:
2.1.1. Получить 2 аргумент для собственного инвайта, если нет - проходит мимо. Создать поток на повышение ранга с рп

Если следовать без проверки, то игрок может быть задерживает хоть 5, 10 секунд и принимает. А скрипт поторопился.
Поэтому нужно проверять, что игрок принимался и тогда прогресс выполнение скрипта продолжается. Если отказался - скипает процесс

Рекомендую изменить либ imgui на mimgui и обновить функции
mimgui:
Ты можешь сделать пример как это должно быть так как я только начал писать код и плохо понимаю
 

kyrtion

Известный
1,022
373
Ты можешь сделать пример как это должно быть так как я только начал писать код и плохо понимаю
Ну сделаем так:
Lua:
local sampev = require('samp.events')

local skinId = 123

---@type table<number, number>
local tempInvite = {
  -- [playerId] = rank,
}

function main()
  repeat wait(0) until isSampAvailable()

  sampRegisterChatCommand('in', function(arg)
    if string.len(arg) == 0 or not arg:find('^%d+%s*%d*$') then
      return sampAddChatMessage('Использование: /in [ID] [ранг]', -1)
    end

    local playerId, rank = arg:match('^(%d+)%s*(%d*)$')
    playerId = tonumber(playerId)
    rank = tonumber(rank)
    if not playerId then return end   -- это оставляю чтобы LLS не затупился, не обращайте на внимание

    -- проверка на существование игрока, находится ли на сервере и в стриме (радар)
    if not sampIsPlayerConnected(playerId) then
      return sampAddChatMessage('Игрок, который Вы указали ID, не в сети!', -1)
    end
    local result, char = sampGetCharHandleBySampPlayerId(playerId)
    if not result or not doesCharExist(char) then
      return sampAddChatMessage('Игрок, который Вы указали ID, не в стриме!', -1)
    end

    -- чекаем на 10 метров - своего педа и игрока
    local myPos, playerPos = { getCharCoordinates(PLAYER_PED) }, { getCharCoordinates(char) }
    local distance = getDistanceBetweenCoords3d(   -- распакуем коорды (x, y, z) из таблицы {}
      table.unpack(myPos),
      table.unpack(playerPos)
    )
    if distance < 10 then
      return sampAddChatMessage('Игрок, который Вы указали ID, находится далеко!', -1)
    end

    -- проверка прошли, принимаем
    -- если команды с задержкой, обязательно с потоком
    local commandInvite = string.format('/invite %d', playerId)
    lua_thread.create(function()
      sampSendChat('/me передал бандану человеку напротив')
      wait(1000)
      sampSendChat(commandInvite)
      if type(rank) == 'number' then
        tempInvite[playerId] = rank
      else
        local fmt = string.format(
          'Вы приняли игрока %s[%d] без ранга',
          sampGetPlayerNickname(playerId), playerId
        )
        sampAddChatMessage(fmt, -1)
      end
    end)
  end)
end

-- после main()
function sampev.onServerMessage(color, text)
  if false and color and text then         -- заменить на свои условия, для авто-повышение, включая проверка в :find
    local playerId = text:match('(%d+)')   -- получение ид игрока после инвайта в чате
    playerId = tonumber(playerId)          -- конвертируем строка на числа
    if not playerId then return end        -- это оставляю чтобы LLS не затупился, не обращайте на внимание
    -- если там прописывается ник без ид'а, тогда получить ник и его узнать ид
    local rank = tempInvite[playerId]
    if rank then   -- если в временной таблице существует игрок с рангом
      local commandGiverank = string.format('/giverank %d %d', playerId, rank)
      local commandGiveskin = string.format('/giveskin %d %d', playerId, skinId)
      local fmt = string.format(
        'Вы приняли игрока %s[%d] с %d рангом и %d скин',
        sampGetPlayerNickname(playerId), playerId,
        rank, skinId
      )
      lua_thread.create(function()
        wait(1000)   -- остатки КД после инвайта
        sampSendChat(commandGiverank)
        wait(1000)
        sampSendChat(commandGiveskin)
        sampAddChatMessage(fmt, -1)
      end)
      table.remove(tempInvite, playerId)
    end
  end
end

В sampev.onServerMessage меняешь на свои условия
 

Drey4ik

Новичок
3
0
Кто может написать скрипт который показывает в чате кто тебя убил и из чего "Такой скрипт уже есть но он не работает на аризоне и на рп серверах я говорю про by Kill"