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

Myradov|

Известный
361
106
return {color, text:gsub("Петя", "Вася")}

Код
Lua:
function imgui.OnDrawFrame()
    local resX, resY = getScreenResolution()
    if main_window_state.v then
        imgui.ShowCursor = true
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(555, 555), imgui.Cond.FirstUseEver)
                imgui.Begin(u8"тут чето будет", main_window_state)
        if imgui.Button(u8'Информация', imgui.ImVec2(135, 30)) then uu() menu[1] = true end imgui.SameLine()
        if imgui.Button(u8'Основные функции', imgui.ImVec2(135, 30)) then uu()  menu[2] = true end imgui.SameLine()
        if imgui.Button(u8'Биндер', imgui.ImVec2(135, 30)) then uu()  menu[3] = true end
        imgui.Separator()
        imgui.NewLine()
        imgui.SameLine(3)
   
     if menu[1] then
     if imgui.CollapsingHeader(u8"Меры наказаний") then
хватит или еще дальше кидать?
 

ufdhbi

Известный
Проверенный
1,460
866
Lua:
function imgui.OnDrawFrame()
    local resX, resY = getScreenResolution()
    if main_window_state.v then
        imgui.ShowCursor = true
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(555, 555), imgui.Cond.FirstUseEver)
                imgui.Begin(u8"тут чето будет", main_window_state)
        if imgui.Button(u8'Информация', imgui.ImVec2(135, 30)) then uu() menu[1] = true end imgui.SameLine()
        if imgui.Button(u8'Основные функции', imgui.ImVec2(135, 30)) then uu()  menu[2] = true end imgui.SameLine()
        if imgui.Button(u8'Биндер', imgui.ImVec2(135, 30)) then uu()  menu[3] = true end
        imgui.Separator()
        imgui.NewLine()
        imgui.SameLine(3)
  
     if menu[1] then
     if imgui.CollapsingHeader(u8"Меры наказаний") then
хватит или еще дальше кидать?
еще
 

Myradov|

Известный
361
106
Lua:
function imgui.OnDrawFrame()
    local resX, resY = getScreenResolution()
    if main_window_state.v then
        imgui.ShowCursor = true
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(555, 555), imgui.Cond.FirstUseEver)
                imgui.Begin(u8"AdmSoft by Myradov", main_window_state)
        if imgui.Button(u8'Информация', imgui.ImVec2(135, 30)) then uu() menu[1] = true end imgui.SameLine()
        if imgui.Button(u8'Основные функции', imgui.ImVec2(135, 30)) then uu()  menu[2] = true end imgui.SameLine()
        if imgui.Button(u8'Биндер', imgui.ImVec2(135, 30)) then uu()  menu[3] = true end
        imgui.Separator()
        imgui.NewLine()
        imgui.SameLine(3)
    
     if menu[1] then
     if imgui.CollapsingHeader(u8"Меры наказаний") then
         local tx = [[
1. Использование багов/недоработок сервера.
1.1 Любой сбив, багоюз (от 3 случаев нарушения)сначала предупреждение, jail 120
1.2 Багоюз иммущества, махинации, слив аккаунта ban 999 + banip
1.3 Багоюз сена на мото/авто (нужно отыграть) предупреждение, jail 20
1.4 Багоюз с грушей в спорт.зале предупреждение, jail 60

2. Нарушение РП режима сервера.
2.1 SpawnKill, PowerGaming, TeamKill, RepeatKill, Death Match id Green Zone jail 60
2.2 Death Match, DriveBy, +С в стену, интерьер от смерти jail 60
2.3 Death Match на слёте jail 180
2.4 Уход/афк/офф от рп, смерти, ареста, +С в игрока jail 180
2.5 Массовый SpawnKill, TeamKill, Death Match(3+ игрока), Death Match in ZZ(3+ игрока) warn
2.6 НонРП поведение, описание персонажа(/desc), ситуации(/action) предупреждение, jail 30
2.7 НонРП езда (ЕПП и прочее) предупреждение, jail 30
2.8 НонРП ник jail 3000 до смены ника
2.10 NonRP Развод ban 30
2.11 NonRP установка объектов во фракциях jail 60
2.12 Биндер во фракции, на рп ситуации. jail 60
2.13 Неадекватное название лавки/баннера jail 30 (+удаление баннера)
2.14 Помеха (флуд паспортом/афк и т.д) /sethp 0
2.15 БХ во время RolePlay Situation предупреждение, jail 30
2.16 Прокачка Заработной Платы в оррганизациях предупреждение, jail 30

3. Нарушение правил общения в чате.
3.1 Оффтоп в репорт mute 30
3.2 Ненормативная лексика в OOC чаты, капс mute 30
3.3 Неадекватное поведение mute 60
3.4 Оскорбления в ООС, Оскорбление администрации mute 120
3.5 MetaGaming, транслит, флуд mute 30 (флуд - 60)
3.6 Багоюз "1.1.1.1.1 сообщение" (причина: не средство связи) mute 60
3.7 Игра через /try mute 60
3.8 Упоминание родных без РП причины, или в ООС чат mute 300
3.9 Оскорбление родных без РП причины, или в ООС чат ban 3+
3.10 Использование"лесенки" (Пример: ПрОдАетСя ДоМ пОд НомЕроМ) mute 60
3.11 Обман администрации mute 300 ban 1-5
3.12 Реклама сторонних ресурсов ban 30
3.13 Выдача себя за администратора. mute 120
3.14 Розжиг без Рп причины, или в ООС чат ban 2
3.15 Реклама в /vr (с 14:00 до 20:00) mute 40
]]       
local tx1 = [[4. Правила голосового чата.
4.1 MetaGaming mute 60
4.2 Включение музыки mute 60
4.3 Издавать разные звуки, мешающие игрокам mute 60
4.4 Реклама сторонних ресурсов ban 30
4.5 Упоминание родных без РП причины mute 300
4.6 Оскорбление родных без РП причины ban 3
4.7 Нарушение тишины, если она была потребована администрацией mute 60

5. Софт и прочее
5.1 Мультиаккаунт ban 15 основа + ban 999 твинки
5.2 Любое стороннее ПО, создающие помехи игре (вредительские) - каршот, рванка и т.п. banip
5.3 Любой софт, запрещённые клео ban 10
5.4 Взлом аккаунтов, слив аккаунтаban 999+ banip
5.5 Снятие с поста лидера На усмотрение ГСа
5.6 Несоблюдение запрета на оплату бизнеса заместителями ban 10
5.7 Неадекватные надписи на лавках на ЦР, баннерах, такси, desc, action предупреждение, jail 30
5.8 Изменение биндов на клавишу. (Ускорение работы на механиках, по типу АХК, прыжок на велосипеде на скролл мышки и т.п. ) warn
5.9 ЦК по одобрению обоих сторон и одобрение со стороны следящих за биографиями Смена ника за свой счёт/за счет администрации
5.10 Оскорбление проекта ban 30
5.11 Использование песочницы/песка ban 10
]]
        imgui.Text(u8(tx))
        imgui.Text(u8(tx1))
    
    end
 

samperzer

Участник
40
2
можно как-то сделать, чтобы когда появлялся на карте чекпоинт, то на него автоматически ставилась метка (типа как игроком)??
 

bab0n

Известный
95
10
тебе ж скинули уже

ML] (error) toster.lua: D:\CUSTOM GTA\moonloader\lib\samp\events\core.lua:91: assertion failed!
stack traceback:
[C]: in function 'assert'
D:\CUSTOM GTA\moonloader\lib\samp\events\core.lua:91: in function <D:\CUSTOM GTA\moonloader\lib\samp\events\core.lua:54>
[ML] (error) toster.lua: Script died due to an error. (0805613C)

C одним я разобрался, теперь вопрос, как Васю перекрасить
Lua:
while true do
        wait(0)
        text, prefix, color, pcolor = sampGetChatString(99)
        text = text:gsub('Петя', 'Вася')
        sampSetChatString(99, text, prefix, color, pcolor)
    end
?
 
Последнее редактирование:

mails2k18

Участник
45
0
Приветствую, подскажите пожалуйста, как получить ник игрока через id?
Нужно, чтобы я вводил команду, например /zap 228 и мне в чат выводилось выбран ник Enri_Pupkin
А Enri_Pupkin у нас к примеру находится под id 228
 

xbyte

Активный
111
95
Приветствую, подскажите пожалуйста, как получить ник игрока через id?
Нужно, чтобы я вводил команду, например /zap 228 и мне в чат выводилось выбран ник Enri_Pupkin
А Enri_Pupkin у нас к примеру находится под id 228
 
  • Нравится
Реакции: mails2k18

mails2k18

Участник
45
0
Помогите найти ошибку, данные выписываются всегда на человека, у которого ID = 0
@L1ckt0r

Lua:
------------------ запрет по id
if mainIni10.zapret.zapretid then
local idnickzapret = string.match(param, '(%d+)') -- Если в команде указано значение
    if #param == 0 then
        sampAddChatMessage('{1288E8}[#Mails scripts]: {ff1200}Системная ошибка: {FFFFFF}Укажите ID игрока [/zapret ID]', main_color)
    else
        lua_thread.create(function() -- При использовании WAIT вне потока MAIN
        local idoopchelika = sampGetPlayerNickname(playerid):gsub('_', ' ')
        sampAddChatMessage('{1288E8}[#Mails scripts]: {FFFFFF} Вы запретили адвокатам выпуск ООП - {FF8000} '..idoopchelika..'', main_color)
        sampSendChat ('/me взял в руки рацию, после чего начал что-то говорить')
        wait(1500)
        sampSendChat ('/b /dep Mayor, Дело на имя '..idoopchelika..' рассмотрению не подлежит.')
        end) -- Конец потока WAIT вне MAIN
    end   
end
------------------ / запрет по id
 

samperzer

Участник
40
2
можно как-то сделать, чтобы когда появлялся на карте чекпоинт, то на него автоматически ставилась метка (типа как игроком)??
 

AntonNeath

Известный
252
109
можно как-то сделать, чтобы когда появлялся на карте чекпоинт, то на него автоматически ставилась метка (типа как игроком)??
Почаще гляди в полезные сниппеты и функции. Я взял код целиком от туда, и добавил 2 строчки.
Lua:
require "lib.sampfuncs"


function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    sampRegisterChatCommand("mycmd", cmd)

    while true do wait(0) end
end

function cmd(param)
    if isPlayerPlaying(playerHandle) then
        local posX, posY, posZ = getCharCoordinates(playerPed)
        local res, x, y, z = SearchMarker(posX, posY, posZ, 50.0, false)
        if res then
            sampAddChatMessage(string.format("Найден обычный маркер в координатах %.2f %.2f %.2f", x, y, z), -1)
            setTargetBlipCoordinates(x, y, z)
        else
            res, x, y, z = SearchMarker(posX, posY, posZ, 50.0, true)
            if res then
                sampAddChatMessage(string.format("Найден гоночный маркер в координатах %.2f %.2f %.2f", x, y, z), -1)
                setTargetBlipCoordinates(x, y, z)
            else
                sampAddChatMessage("Маркер не найден", -1)
            end
        end
    end
end

function SearchMarker(posX, posY, posZ, radius, isRace)
    local ret_posX = 0.0
    local ret_posY = 0.0
    local ret_posZ = 0.0
    local isFind = false

    for id = 0, 31 do
        local MarkerStruct = 0
        if isRace then MarkerStruct = 0xC7F168 + id * 56
        else MarkerStruct = 0xC7DD88 + id * 160 end
        local MarkerPosX = representIntAsFloat(readMemory(MarkerStruct + 0, 4, false))
        local MarkerPosY = representIntAsFloat(readMemory(MarkerStruct + 4, 4, false))
        local MarkerPosZ = representIntAsFloat(readMemory(MarkerStruct + 8, 4, false))

        if MarkerPosX ~= 0.0 or MarkerPosY ~= 0.0 or MarkerPosZ ~= 0.0 then
            if getDistanceBetweenCoords3d(MarkerPosX, MarkerPosY, MarkerPosZ, posX, posY, posZ) < radius then
                ret_posX = MarkerPosX
                ret_posY = MarkerPosY
                ret_posZ = MarkerPosZ
                isFind = true
                radius = getDistanceBetweenCoords3d(MarkerPosX, MarkerPosY, MarkerPosZ, posX, posY, posZ)
            end
        end
    end

    return isFind, ret_posX, ret_posY, ret_posZ
end
 

samperzer

Участник
40
2
Почаще гляди в полезные сниппеты и функции. Я взял код целиком от туда, и добавил 2 строчки.
Lua:
require "lib.sampfuncs"


function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end
    sampRegisterChatCommand("mycmd", cmd)

    while true do wait(0) end
end

function cmd(param)
    if isPlayerPlaying(playerHandle) then
        local posX, posY, posZ = getCharCoordinates(playerPed)
        local res, x, y, z = SearchMarker(posX, posY, posZ, 50.0, false)
        if res then
            sampAddChatMessage(string.format("Найден обычный маркер в координатах %.2f %.2f %.2f", x, y, z), -1)
            setTargetBlipCoordinates(x, y, z)
        else
            res, x, y, z = SearchMarker(posX, posY, posZ, 50.0, true)
            if res then
                sampAddChatMessage(string.format("Найден гоночный маркер в координатах %.2f %.2f %.2f", x, y, z), -1)
                setTargetBlipCoordinates(x, y, z)
            else
                sampAddChatMessage("Маркер не найден", -1)
            end
        end
    end
end

function SearchMarker(posX, posY, posZ, radius, isRace)
    local ret_posX = 0.0
    local ret_posY = 0.0
    local ret_posZ = 0.0
    local isFind = false

    for id = 0, 31 do
        local MarkerStruct = 0
        if isRace then MarkerStruct = 0xC7F168 + id * 56
        else MarkerStruct = 0xC7DD88 + id * 160 end
        local MarkerPosX = representIntAsFloat(readMemory(MarkerStruct + 0, 4, false))
        local MarkerPosY = representIntAsFloat(readMemory(MarkerStruct + 4, 4, false))
        local MarkerPosZ = representIntAsFloat(readMemory(MarkerStruct + 8, 4, false))

        if MarkerPosX ~= 0.0 or MarkerPosY ~= 0.0 or MarkerPosZ ~= 0.0 then
            if getDistanceBetweenCoords3d(MarkerPosX, MarkerPosY, MarkerPosZ, posX, posY, posZ) < radius then
                ret_posX = MarkerPosX
                ret_posY = MarkerPosY
                ret_posZ = MarkerPosZ
                isFind = true
                radius = getDistanceBetweenCoords3d(MarkerPosX, MarkerPosY, MarkerPosZ, posX, posY, posZ)
            end
        end
    end

    return isFind, ret_posX, ret_posY, ret_posZ
end
можно файлом?