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

shizzard

Участник
150
7
Как записывать все ближайшие ники в маленьком радиусе, ну люди не далеко когда в строю стоят, чтобы их ники скопировать в буфер обмена?
 

Myradov|

Известный
361
106
Кто-нибудь может объяснить мне принципы работы сего творения?:
Уже 3 день бьюсь над тем, чтобы оно хоть что-то загрузило
Кинь код, мы не экстрасенсы
 

davidhomosdean

Новичок
10
0
Телепорт с контрольной точки не работает. Почему нет?


Код:
 local q = require 'lib.samp.events'
local vector = require 'vector3d'
local tp, sync = false, false
local tpCount, timer = 0, 0

function main ()
    while not isSampAvailable () do wait (0) end
    sampRegisterChatCommand ('ftp', function ()
    lua_thread.create (function ()
        if tp then return sampAddChatMessage ('already teleporting', -1) end

            blip, blipX, blipY, blipZ = getTargetBlipCoordinatesFixed ()
            if blip then
                sync = true
                charPosX, charPosY, charPosZ = getCharCoordinates (playerPed)
                local distan = getDistanceBetweenCoords3d (blipX, blipY, charPosZ, charPosX, charPosY, charPosZ)
                if distan <13 then return setCharCoordinates (playerPed, blipX, blipY, blipZ) end
                tp = true
            end
        end)
    end)
        sampRegisterChatCommand ('ftpc', function ()
    lua_thread.create (function ()
        if tp then return sampAddChatMessage ('already teleporting', -1) end

            blip, blipX, blipY, blipZ = SearchMarker ()
            if blip then
                sync = true
                charPosX, charPosY, charPosZ = getCharCoordinates (playerPed)
                local distan = getDistanceBetweenCoords3d (blipX, blipY, charPosZ, charPosX, charPosY, charPosZ)
                if distan <13 then return setCharCoordinates (playerPed, blipX, blipY, blipZ) end
                tp = true
            end
        end)
    end)
        while true do wait (0)
            if os.clock () - timer> 2500 and sync then
              timer, tpCount = 0, 0
              sync = true
              sampForceOnfootSync ()
              sync = false
              sampForceOnfootSync ()
            end
            if tp then
                if getDistanceBetweenCoords3d (blipX, blipY, blipZ, charPosX, charPosY, charPosZ)> 13 then
                    vectorX = blipX - charPosX
                    vectorY = blipY - charPosY
                    vectorZ = blipZ - charPosZ
                    local vec = vector (vectorX, vectorY, vectorZ)
                    vec: normalize ()
                    charPosX = charPosX + vec.x * 13
                    charPosY = charPosY + vec.y * 13
                    charPosZ = charPosZ + vec.z * 13

                    sendOnfootSync (charPosX, charPosY, charPosZ)
                    sendOnfootSync (charPosX, charPosY, charPosZ)
                    tpCount = tpCount + 1
                    if tpCount == 5 then
                      sendOnfootSync (charPosX, charPosY + 55, charPosZ)
                      tpCount = 0
                    end
                else
                  sendOnfootSync (charPosX, charPosY, charPosZ)
                  printStringNow ('~ g ~ teleported successfully.', 4000)
                  setCharCoordinates (playerPed, blipX, blipY, blipZ)
                  sendOnfootSync (charPosX, charPosY + 55, charPosZ)
                  sampForceAimSync ()
                  sampForceOnfootSync ()
                  tp = false
                end
            end
        end
    wait (-1)
end

function q.onSetPlayerPos (p)
    if sync then
        timer = os.clock ()
        return false
    end
end

function q.onSendPlayerSync (data)
    if tp then return false end
end

function samp_create_sync_data (sync_type, copy_from_player)
    local ffi = require 'ffi'
    local sampfuncs = require 'sampfuncs'
    - from SAMP.Lua
    local raknet = require 'samp.raknet'
    --require 'samp.synchronization'

    copy_from_player = copy_from_player or true
    local sync_traits = {
        player = {'PlayerSyncData', raknet.PACKET.PLAYER_SYNC, sampStorePlayerOnfootData},
        vehicle = {'VehicleSyncData', raknet.PACKET.VEHICLE_SYNC, sampStorePlayerIncarData},
        passenger = {'PassengerSyncData', raknet.PACKET.PASSENGER_SYNC, sampStorePlayerPassengerData},
        aim = {'AimSyncData', raknet.PACKET.AIM_SYNC, sampStorePlayerAimData},
        trailer = {'TrailerSyncData', raknet.PACKET.TRAILER_SYNC, sampStorePlayerTrailerData},
        unoccupied = {'UnoccupiedSyncData', raknet.PACKET.UNOCCUPIED_SYNC, nil},
        bullet = {'BulletSyncData', raknet.PACKET.BULLET_SYNC, nil},
        spectator = {'SpectatorSyncData', raknet.PACKET.SPECTATOR_SYNC, nil}
    }
    local sync_info = sync_traits [sync_type]
    local data_type = 'struct' .. sync_info [1]
    local data = ffi.new (data_type, {})
    local raw_data_ptr = tonumber (ffi.cast ('uintptr_t', ffi.new (data_type .. '*', data)))
    - copy player's sync data to the allocated memory
    if copy_from_player then
        local copy_func = sync_info [3]
        if copy_func then
            local _, player_id
            if copy_from_player == true then
                _, player_id = sampGetPlayerIdByCharHandle (PLAYER_PED)
            else
                player_id = tonumber (copy_from_player)
            end
            copy_func (player_id, raw_data_ptr)
        end
    end
    - function to send packet
    local func_send = function ()
        local bs = raknetNewBitStream ()
        raknetBitStreamWriteInt8 (bs, sync_info [2])
        raknetBitStreamWriteBuffer (bs, raw_data_ptr, ffi.sizeof (data))
        raknetSendBitStreamEx (bs, sampfuncs.HIGH_PRIORITY, sampfuncs.UNRELIABLE_SEQUENCED, 1)
        raknetDeleteBitStream (bs)
    end
    - metatable to access sync data and 'send' function
    local mt = {
        __index = function (t, index)
            return data [index]
        end,
        __newindex = function (t, index, value)
            data [index] = value
        end
    }
    return setmetatable ({send = func_send}, mt)
end

function sendOnfootSync (x, y, z)
    local data = samp_create_sync_data ('player')
    data.position = {x, y, z}
    data.moveSpeed = {0.899999, 0.899999, -0.899999}
    data.send ()
end

function getTargetBlipCoordinatesFixed () - snippet by Azller Lollison
    local bool, x, y, z = getTargetBlipCoordinates (); if not bool then return false end
    requestCollision (x, y); loadScene (x, y, z)
    local bool, x, y, z = getTargetBlipCoordinates ()
    return bool, x, y, z
end

function SearchMarker (posX, posY, posZ)
    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
        MarkerStruct = 0xC7F168 + id * 56
        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
                ret_posX = MarkerPosX
                ret_posY = MarkerPosY
                ret_posZ = MarkerPosZ
                isFind = true
        end
    end
    return isFind, ret_posX, ret_posY, ret_posZ
  end
[/ CODE]
 

looney_

Участник
48
10
как получить координаты полоски HP на экране, выписывая ее через rendertext? типо там rendertext и нужно указывать координаты, можно как нибудь узнать координаты полоски HP, что бы они автоматически отправлялись в то значение
 

Fomikus

Известный
Проверенный
475
345
как получить координаты полоски HP на экране, выписывая ее через rendertext? типо там rendertext и нужно указывать координаты, можно как нибудь узнать координаты полоски HP, что бы они автоматически отправлялись в то значение
Health PosX - 0x58EE87
Health PosY - 0x58EE68
Health Width - 0x5892D8
Health Height - 0x589358
Health Color - 0x58932A
Health Border - 0x589353
Health Percentage - 0x589355
 

Wycmpblu

Известный
152
31
как сделать проверку строки из txt файла на существование? Например ввожу команду /check test_test и если строка test_test содержится в файле то выполняется мое действие
 
Последнее редактирование:

wintreist

Активный
308
71
Кинь код, мы не экстрасенсы
Lua:
function main()
    autoupdate("http://raw.githubusercontent.com/Wintreist/mafiasSampPub/master/autoupdate.json", '['..string.upper(thisScript().name)..']: ', "https://blast.hk/threads/47805/")
    wait(-1)
end


function autoupdate(json_url, prefix, url)
  local dlstatus = require('moonloader').download_status
  local json = getWorkingDirectory() .. '\\'..thisScript().name..'-version.json'
  if doesFileExist(json) then os.remove(json) end
  downloadUrlToFile(json_url, json,
    function(id, status, p1, p2)
      if status == dlstatus.STATUSEX_ENDDOWNLOAD then
        if doesFileExist(json) then
          local f = io.open(json, 'r')
          if f then
            local info = decodeJson(f:read('*a'))
            updatelink = info.updateurl
            updateversion = info.latest
            inilink = info.ini
            latestcfg = info.latestcfg
            f:close()
            os.remove(json)
            if updateversion ~= thisScript().version then
              lua_thread.create(function(prefix)
                local dlstatus = require('moonloader').download_status
                print(prefix..'Обнаружено обновление. Пытаюсь обновиться c '..thisScript().version..' на '..updateversion)
                wait(250)
                downloadUrlToFile(updatelink, thisScript().path,
                  function(id3, status2, p13, p23)
                    if status2 == dlstatus.STATUS_DOWNLOADINGDATA then
                      print(string.format('Загружено %d из %d.', p13, p23))
                    elseif status2 == dlstatus.STATUS_ENDDOWNLOADDATA then
                      print('Загрузка обновления завершена.')
                      print(prefix..'Обновление завершено!')
                      goupdatestatus = true
                      lua_thread.create(function() wait(500) thisScript():reload() end)
                    end
                    if status2 == dlstatus.STATUSEX_ENDDOWNLOAD then
                      if goupdatestatus == nil then
                        print(prefix..'Обновление прошло неудачно. Запускаю устаревшую версию..')
                        update = false
                      end
                    end
                  end
                )
                end, prefix
              )
            end
            goupdatestatus = nil
            if cfg == nil or cfg.version.version ~= tonumber(latestcfg) then
                lua_thread.create(function(prefix)
                local dlstatus = require('moonloader').download_status
                local path = getWorkingDirectory() .. 'config\\mafias.ini'
                print('Отсутствует .ini файл, загружаю')
                wait(250)
                downloadUrlToFile(inilink, path,
                  function(id3, status2, p13, p23)
                    if status2 == dlstatus.STATUS_DOWNLOADINGDATA then
                      print(string.format('Загружено %d из %d.', p13, p23))
                    elseif status2 == dlstatus.STATUS_ENDDOWNLOADDATA then
                      print('Загрузка .ini файла завершена')
                      goupdatestatus = true
                      lua_thread.create(function() wait(500) thisScript():reload() end)
                    end
                    if status2 == dlstatus.STATUSEX_ENDDOWNLOAD then
                      if goupdatestatus == nil then
                        print('Загрузить .ini не удалось')
                        update = false
                      end
                    end
                  end
                )
                end, prefix
              )
            end
          end
        update = false
        end
      end
    end)
  while update ~= false do wait(100) end
end
 

Skymbriay

Потрачен
165
16
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Как сделать рендер на оленя работающий нормально
 

CaJlaT

07.11.2024 14:55
Модератор
2,830
2,660
как сделать проверку строки из txt файла на существование? Например ввожу команду /check test_test и если строка test_test содержится в файле то выполняется мое действие
Работа с файлами, как по мне, самое простое, что может быть в луа....
Lua:
local path = getWorkingDirectory()..'\\resource' -- папка с файлами (gta/moonloader/resource)
if not doesDirectoryExist(path) then createDirectory(path) end -- если нет папки, то создаём её
function main()
    if not isSampLoaded() and not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    sampRegisterChatCommand('/create', function(arg)
        if #arg == 0 then return sampAddChatMessage('Ошибка, используйте //create [file]', -1) end
        if not arg:find('%.txt') then arg = arg..'.txt' end -- автоматическое добавление расширения файла
        if doesFileExist(path..'\\'..arg) then return sampAddChatMessage('Ошибка, такой файл уже существует!', -1) end
        local f = io.open(path..'\\'..arg, 'w+')
        f:close()
        sampAddChatMessage('Файл '..arg..' был успешно создан!', -1)
    end)
    sampRegisterChatCommand('/delete', function(arg)
        if #arg == 0 then return sampAddChatMessage('Ошибка, используйте //delete [file]', -1) end
        if not arg:find('%.txt') then arg = arg..'.txt' end -- автоматическое добавление расширения файла
        if not doesFileExist(path..'\\'..arg) then return sampAddChatMessage('Ошибка, данного файла не существует!', -1) end
        os.remove(path..'\\'..arg)
        sampAddChatMessage('Файл '..arg..' был успешно удалён!', -1)
    end)
    sampRegisterChatCommand('/read', function(arg)
        if #arg == 0 then return sampAddChatMessage('Ошибка, используйте //read [file]', -1) end
        if not arg:find('%.txt') then arg = arg..'.txt' end -- автоматическое добавление расширения файла
        if not doesFileExist(path..'\\'..arg) then return sampAddChatMessage('Ошибка, данного файла не существует!', -1) end
        local f = io.open(path..'\\'..arg, 'r')
        local text = f:read('*a')
        f:close()
        sampShowDialog(9999, arg, '{FFFFFF}'..text, 'OK')
    end)
    sampRegisterChatCommand('/check', function(arg) -- да, можно проще, но так как по мне нагляднее
        if #arg == 0 then return sampAddChatMessage('Ошибка, используйте //check [file] [text]', -1) end
        local file, search = arg:match('(.-) (.+)') -- разделение одного аргумента на 2
        if #search == 0 then return sampAddChatMessage('Ошибка, используйте //check [file] [text]', -1) end
        if not file:find('%.txt') then file = file..'.txt' end -- автоматическое добавление расширения файла
        if not doesFileExist(path..'\\'..file) then return sampAddChatMessage('Ошибка, данного файла не существует!', -1) end
        local i = 0
        local text = ''
        for line in io.lines(path..'\\'..file) do
            i = i + 1
            if line:find(search) then
                text = text..'\n'..i..'. '..line
            end
        end
        if text == '' then return sampAddChatMessage('Ошибка, ничего не найдено!', -1) end
        sampShowDialog(9999, file, '{FFFFFF}'..text, 'OK')
    end)
    sampRegisterChatCommand('/edit', function(arg)
        if #arg == 0 then return sampAddChatMessage('Ошибка, используйте //edit [file]', -1) end
        if not arg:find('%.txt') then arg = arg..'.txt' end -- автоматическое добавление расширения файла
        filepath = path..'\\'..arg
        if not doesFileExist(filepath) then return sampAddChatMessage('Ошибка, данного файла не существует!', -1) end
        lines = {} -- массив линий файла
        for line in io.lines(filepath) do
            table.insert(lines, line)
        end
        sampShowDialog(7777, arg, '{00FF00}Добавить строчку\n'..table.concat(lines, '\n'), 'Выбрать', 'Закрыть', 2)
        lua_thread.create(dialog)
    end)
    while true do
        wait(0)
    end
end
function dialog()
    while sampIsDialogActive() do
        wait(0)
        if sampGetCurrentDialogId() ~= 7777 then break end
        local result, button, list, input = sampHasDialogRespond(7777)
        if result then
            if button == 1 then
                if list == 0 then
                    line = #lines + 1
                    sampShowDialog(8888, '{00FF00}Добавить строчку строчку:', '{FFFFFF}Введите текст', 'OK', 'Отмена', 1)
                    lua_thread.create(dialog2)
                else
                    line = list
                    sampShowDialog(8888, '{FFFFFF}Редактировать строчку:', '{FFFFFF}'..lines[line], 'OK', 'Отмена', 1)
                    lua_thread.create(dialog2)
                end
            end
        end
    end
end
function dialog2()
    while sampIsDialogActive() do
        wait(0)
        if sampGetCurrentDialogId() ~= 8888 then break end
        local result, button, list, input = sampHasDialogRespond(8888)
        if result then
            if button == 1 then
                lines[line] = input
                local file = io.open(filepath, 'w')
                file:write(table.concat(lines, "\n"))
                file:close()
            end
        end
    end
end
 

Вложения

  • zdarova.lua
    4.9 KB · Просмотры: 6
  • Bug
Реакции: darkjer

kizn

\ 0 _ 0 /
Всефорумный модератор
2,407
2,090
Как из этого диалогового окна взять ник (Vinnie_Underwood) и транспорт (Stallion)?
Хочу сделать сообщение в чат "Игрок Vinnie_Underwood дал вам копию ключей от транспорта Stallion"

WBb7w1B.png