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

Mockingbird

Новичок
13
2
Всем привет, нужна помощь. Есть такой кусок кода:


Код:
elseif text:find("посадил:") then
        sendtg("Администратор что-то пишет")
Этот функция читает чат сампа и когда вскакивает "посадил" отправляет сообщение в телеграм. Но, мне нужно сделать так, что бы он отправлял, когда "Администратор *ник* посадил в призон игрока *ник*", загвоздка в том, что я не могу понять как сделать так, чтобы он считывал "Администратор *ник* посадил" но, не могу понять как заставить его игнорировать ник админа, так как этот часть меняется. Помогите :/
 

Arahis

Новичок
7
1
Всем привет, нужна помощь. Есть такой кусок кода:


Код:
elseif text:find("посадил:") then
        sendtg("Администратор что-то пишет")
Этот функция читает чат сампа и когда вскакивает "посадил" отправляет сообщение в телеграм. Но, мне нужно сделать так, что бы он отправлял, когда "Администратор *ник* посадил в призон игрока *ник*", загвоздка в том, что я не могу понять как сделать так, чтобы он считывал "Администратор *ник* посадил" но, не могу понять как заставить его игнорировать ник админа, так как этот часть меняется. Помогите :/
 
  • Нравится
Реакции: Mockingbird

Дядя Энрик.

Активный
338
81
в чём прикол?
Код:
local imgui = require 'mimgui'
local encoding = require 'encoding'
local effil = require 'effil'
local memory = require 'memory'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local new = imgui.new
local renderWindow = new.bool(false)
imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil
end)
local newFrame = imgui.OnFrame(
    function() return renderWindow[0] end,
    function(player)
        local resX, resY = getScreenResolution()
        local sizeX, sizeY = 300, 300
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(sizeX, sizeY), imgui.Cond.FirstUseEver)
        imgui.Begin('Main Window', renderWindow)
        imgui.ImageURL("https://items.shinoa.tech/images/model/2296.png", imgui.ImVec2(256, 256), true)
        imgui.End()
    end
)
sampRegisterChatCommand('urlt', function()
    renderWindow[0] = not renderWindow[0]
end)
function handleAsyncHttpRequestThread(runner, resolve, reject)
  local status, err
  repeat
    status, err = runner:status()
    wait(0)
  until status ~= 'running'
  if not err then
    if status == 'completed' then
      local result, response = runner:get()
      if result then
        resolve(response)
      else
        reject(response)
      end
      return
    elseif status == 'canceled' then
      return reject(status)
    end
  else
    return reject(err)
  end
end
function asyncHttpRequest(method, url, args, resolve, reject)
   local request_thread = effil.thread(function (method, url, args)
      local requests = require 'requests'
      local result, response = pcall(requests.request, method, url, args)
      if result then
         response.json, response.xml = nil, nil
         return true, response
      else
         return false, response
      end
   end)(method, url, args)
   -- Если запрос без функций обработки ответа и ошибок.
   if not resolve then resolve = function() end end
   if not reject then reject = function() end end
   -- Проверка выполнения потока
    lua_thread.create(function()
      local runner = request_thread
      while true do
         local status, err = runner:status()
         if not err then
            if status == 'completed' then
               local result, response = runner:get()
               if result then
                  resolve(response)
               else
                  reject(response)
               end
               return
            elseif status == 'canceled' then
               return reject(status)
            end
         else
            return reject(err)
         end
         wait(0)
      end
   end)
end
local md5 = require "md5"

imgui.ImageURL = {
    cache_dir = getWorkingDirectory() .. "/resource/cache",
    download_statuses = {
        INIT = 0,
        DOWNLOADING = 1,
        ERROR = 2,
        SAVED = 3,
        NOT_MODIFIED = 4,
        CACHE_ONLY = 5
    },
    pool = {}
}

function imgui.ImageURL:set_cache(url, image_data, headers)
    if not doesDirectoryExist(self.cache_dir) then
        createDirectory(self.cache_dir)
    end

    local path = ("%s/%s"):format(self.cache_dir, md5.sumhexa(url))
    local file, err = io.open(path, "wb")
    if not file then
        return nil
    end

    local data = { Data = tostring(image_data) }
    if headers["etag"] then
        data["Etag"] = headers["etag"]
    end
    if headers["last-modified"] then
        data["Last-Modified"] = headers["last-modified"]
    end

    file:write(encodeJson(data))
    file:close()
    return path
end

function imgui.ImageURL:get_cache(url)
    local path = ("%s/%s"):format(self.cache_dir, md5.sumhexa(url))
    if not doesFileExist(path) then
        return nil, nil
    end

    local image_data = nil
    local cached_headers = {}

    local file, err = io.open(path, "rb")
    if file then
        local cache = decodeJson(file:read("*a"))
        if type(cache) ~= "table" then
            return nil, nil
        end

        if cache["Data"] ~= nil then
               image_data = cache["Data"]
           end
           if cache["Last-Modified"] ~= nil then
               cached_headers["If-Modified-Since"] = cache["Last-Modified"]
           end
           if cache["Etag"] ~= nil then
               cached_headers["If-None-Match"] = cache["Etag"]
           end

        file:close()
    end
    return image_data, cached_headers
end

function imgui.ImageURL:download(url, preload_cache)
    local st = self.download_statuses
    self.pool[url] = {
        status = st.DOWNLOADING,
        image = nil,
        error = nil
    }
    local cached_image, cached_headers = imgui.ImageURL:get_cache(url)
    local img = self.pool[url]

    if preload_cache and cached_image ~= nil then
        img.image = imgui.CreateTextureFromMemory(memory.strptr(cached_image), #cached_image)
    end

    asyncHttpRequest("GET", url, { headers = cached_headers },
        function(result)
            if result.status_code == 200 then
                img.image = imgui.CreateTextureFromMemory(memory.strptr(result.text), #result.text)
                img.status = st.SAVED
                imgui.ImageURL:set_cache(url, result.text, result.headers)
            elseif result.status_code == 304 then
                img.image = img.image or imgui.CreateTextureFromMemory(memory.strptr(cached_image), #cached_image)
                img.status = st.NOT_MODIFIED
            else
                img.status = img.image and st.CACHE_ONLY or st.ERROR
                img.error = ("Error #%s"):format(result.status_code)
            end
        end,
        function(error)
            img.status = img.image and st.CACHE_ONLY or st.ERROR
            img.error = error
        end
    )
end

function imgui.ImageURL:render(url, size, preload, ...)
    local st = self.download_statuses
    local img = self.pool[url]

    if img == nil then
        self.pool[url] = {
            status = st.INIT,
            error = nil,
            image = nil
        }
        img = self.pool[url]
    end

    if img.status == st.INIT then
        imgui.ImageURL:download(url, preload)
    end
        
    if img.image ~= nil then
        imgui.Image(img.image, size, ...)
    else
        imgui.Dummy(size)
    end
    return img.status, img.error
end

setmetatable(imgui.ImageURL, {
    __call = imgui.ImageURL.render
})
ошибка :168: attempt to call field 'CreateTextureFromMemory' (a nil value)
 

Hidetaka

Новичок
14
1
Что делает функция setGameKeyState? Поясните подробно, пожалуйста.

Что делает функция setGameKeyState? Поясните подробно, пожалуйста.
 

Дядя Энрик.

Активный
338
81
Что делает функция setGameKeyState? Поясните подробно, пожалуйста.

Что делает функция setGameKeyState? Поясните подробно, пожалуйста.
 

.das

Известный
15
2
Приветствую всех, новичок в программировании.
1) Хотел написать скрипт, который отправляет нажатие кнопки N сервере каждые 3 минуты, но появилась проблема, то что сервер не засчитывает нажатие кнопки даже когда оружие в руках у игрока. Как можно решить эту проблему?
Делал через setVirtualKeyDown, но там кнопки нажимается вне игры при свернутом режиме. Также setGameKeyState, но кнопка не всегда прожимается.
Вот код:
Lua:
[/B]
function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('testan', function()
        local data = samp_create_sync_data('player')
        data.weapon = data.weapon + 128
        data.send()
        sampAddChatMessage('N pressed', -1)
    end)
    wait(-1)
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
[B]

2) Второй вопрос как сделать чтобы скрипт нажимал кнопку до тех пор пока не выводится определенное сообщение от сервера? Я понял что через onServerMessage хукнуть сообщение нужно, а как грамотно реализовать не понял.

Буду благодарен за помощь.
 

Hidetaka

Новичок
14
1
Как закрепить камеру за персонажем? Как в ботах по координатам.
 

Binon

Новичок
1
0
Приветствую.
Мне нужен код который будет воспроизводить заранее записанный маршрут, типа вот так:


Код:
[1]
packetId=0
lr=0
ud=0
keys=0
x=0
y=0
z=0
qw=0
qx=0
qy=0
qz=0
qw=0
sa=0
sx=0
sy=0
sz=0
anim=0
flags=0
mode=0
cx=0
cy=0
cz=0
px=0
py=0
pz=0
az=0
zoom=0
wstate=0
unk=0

Либо так:

Код:
{x = 100, qy = 200, qz = 300, y = 400, cx = 500, packetId = 1, wstate = 0, qw = 30, cy = 600, z = 700, zoom = 1.0, cz = 800, keys = "W", az = 90, lr = 0, mode = 1, ud = 0, pz = 100, px = 110, gear = 1, py = 120, sy = 130, qx = 140, sz = 150, sx = 160}

Ну или есть скрипт который позволяет записать маршрут и потом воспроизвести его уже в моем скрипте например по команде /bot
 

Hahker

Новичок
28
0
Как сделать так, чтобы интерфейс /admins закрывался сразу же? а то он открывается и стопит тебя.

Lua:
local sampev = require('lib.samp.events')
local font_flag = require('moonloader').font_flag

local checker_x = 10
local checker_y = 400
local checker_indent = 11
local admins = {}
local arial = renderCreateFont('Lays-Bold', 10, 5)

function compareRanks(a, b)
    local rankOrder = {
        ['Заместитель Главного Администратора'] = 1,
        ['Куратор'] = 2,
        ['Администратор'] = 3,
        ['Старший Модератор'] = 4,
        ['Модератор'] = 5,
        ['Младший Модератор'] = 6
    }

    return rankOrder[a.rank] < rankOrder[b.rank]
end

local adminRanksColors = {
    ['Младший Модератор'] = '6495ed',
    ['Модератор'] = '456cdd',
    ['Старший Модератор'] = 'ffcb00',
    ['Администратор'] = '147f1a',
    ['Куратор'] = '6642cc',
    ['Заместитель Главного Администратора'] = 'ff0000'
}

local isCheckerEnabled = false
local lastCheckTime = os.time()
local isSpectated = false
local isReportShowed = false

function main()
    while not isSampAvailable() do wait(0) end
    sampAddChatMessage('loaded', -1)
    sampRegisterChatCommand('rl1', function()
        isCheckerEnabled = not isCheckerEnabled
        sampAddChatMessage('/admins', -1)

        lua_thread.create(function()
            wait(50) 
            setVirtualKeyDown(27, true) 
            wait(100) 
            setVirtualKeyDown(27, false) 
        end)
    end)

    while true do
        wait(0)
        if isCheckerEnabled then
            local currentTime = os.time()
        
            if currentTime - lastCheckTime >= 4 and (not sampIsChatInputActive() and not isSpectated) then
                sampSendChat('/admins')
                lastCheckTime = currentTime

                lua_thread.create(function()
                    wait(50) 
                    setVirtualKeyDown(27, true) 
                    wait(100) 
                    setVirtualKeyDown(27, false) 
                end)
            end
        end
        renderFontDrawText(arial, 'Администрация в сети:', checker_x, checker_y, 0xFFFFFFFF)
        local y = checker_y
        for _, admin in ipairs(admins) do
            y = y + checker_indent
            renderFontDrawText(arial, ('{%s}%s %s[%d] {ffffff}- REP: %d - STATE: %s - AFK: %s'):format(adminRanksColors[admin.rank], admin.rank, admin.nickname, admin.id, admin.rep, admin.state, admin.afk), checker_x, y, 0xFFFFFFFF)
        end
    end
end

function sampev.onTogglePlayerSpectating(state)
    isSpectated = state
end

addEventHandler('onReceivePacket', function(id, bs, ...)
    if id == 220 then
        raknetBitStreamIgnoreBits(bs, 8)
        local packetType = raknetBitStreamReadInt8(bs)
        if packetType == 46 then -- диалог
            raknetBitStreamIgnoreBits(bs, 72) -- 8*9
            local dialogTitleLen = raknetBitStreamReadInt16(bs)
            local dialogTitle = raknetBitStreamReadString(bs, dialogTitleLen)
            if dialogTitle:find('Администрация в сети') then
                admins = {}
                raknetBitStreamIgnoreBits(bs, 320) -- 8*40
                local dialogTextLen = raknetBitStreamReadInt16(bs)
                local dialogText = raknetBitStreamReadString(bs, dialogTextLen)
                for line in dialogText:gmatch('[^\n]+') do
                    if line:find('Заместитель Главного Администратора') then
                        goto continue
                    end
                    local rank, nickname, id, rep, state, afk = line:match('^%{FFFFFF%}(.*) ([%w_]+)%[(%d+)%]\t(%d+)\t(.*)\t(.*)$')
                    table.insert(admins, {
                        rank = rank,
                        nickname = nickname,
                        id = id,
                        rep = rep,
                        state = state,
                        afk = afk
                    })
                    ::continue::
                end
                table.sort(admins, compareRanks)
            end
        elseif packetType == 41 then
            local textLen = raknetBitStreamReadInt16(bs)
            local jsonString = raknetBitStreamReadString(bs, textLen)
            local jsonData = decodeJson(jsonString)
            if jsonData.show and jsonData.type == "REPORT_SHOW" then
                isReportShowed = jsonData.show == "admin"       
            end
        end
    end
end)
 

Minhjhs

Участник
69
22
Как закрепить камеру за персонажем? Как в ботах по координатам.
Используй эту функцию -
lua:
function setAngle(X, Y)
    local cX, cY, cZ = getActiveCameraCoordinates()
    setCameraPositionUnfixed(0.0, (getHeadingFromVector2d(X - cX, Y - cY) - 90.0) / 57.2957795)
end
X, Y - Точка, куда будет смотреть твоя камера
Но, Чтобы закрепить камеру за персонажем - Я не знаю ответа, сам ищю на протяжении 2х дней, Ответа не нашёл. Даже тему оставил...
 

Arahis

Новичок
7
1
Как сделать так, чтобы интерфейс /admins закрывался сразу же? а то он открывается и стопит тебя.

Lua:
local sampev = require('lib.samp.events')
local font_flag = require('moonloader').font_flag

local checker_x = 10
local checker_y = 400
local checker_indent = 11
local admins = {}
local arial = renderCreateFont('Lays-Bold', 10, 5)

function compareRanks(a, b)
    local rankOrder = {
        ['Заместитель Главного Администратора'] = 1,
        ['Куратор'] = 2,
        ['Администратор'] = 3,
        ['Старший Модератор'] = 4,
        ['Модератор'] = 5,
        ['Младший Модератор'] = 6
    }

    return rankOrder[a.rank] < rankOrder[b.rank]
end

local adminRanksColors = {
    ['Младший Модератор'] = '6495ed',
    ['Модератор'] = '456cdd',
    ['Старший Модератор'] = 'ffcb00',
    ['Администратор'] = '147f1a',
    ['Куратор'] = '6642cc',
    ['Заместитель Главного Администратора'] = 'ff0000'
}

local isCheckerEnabled = false
local lastCheckTime = os.time()
local isSpectated = false
local isReportShowed = false

function main()
    while not isSampAvailable() do wait(0) end
    sampAddChatMessage('loaded', -1)
    sampRegisterChatCommand('rl1', function()
        isCheckerEnabled = not isCheckerEnabled
        sampAddChatMessage('/admins', -1)

        lua_thread.create(function()
            wait(50)
            setVirtualKeyDown(27, true)
            wait(100)
            setVirtualKeyDown(27, false)
        end)
    end)

    while true do
        wait(0)
        if isCheckerEnabled then
            local currentTime = os.time()
       
            if currentTime - lastCheckTime >= 4 and (not sampIsChatInputActive() and not isSpectated) then
                sampSendChat('/admins')
                lastCheckTime = currentTime

                lua_thread.create(function()
                    wait(50)
                    setVirtualKeyDown(27, true)
                    wait(100)
                    setVirtualKeyDown(27, false)
                end)
            end
        end
        renderFontDrawText(arial, 'Администрация в сети:', checker_x, checker_y, 0xFFFFFFFF)
        local y = checker_y
        for _, admin in ipairs(admins) do
            y = y + checker_indent
            renderFontDrawText(arial, ('{%s}%s %s[%d] {ffffff}- REP: %d - STATE: %s - AFK: %s'):format(adminRanksColors[admin.rank], admin.rank, admin.nickname, admin.id, admin.rep, admin.state, admin.afk), checker_x, y, 0xFFFFFFFF)
        end
    end
end

function sampev.onTogglePlayerSpectating(state)
    isSpectated = state
end

addEventHandler('onReceivePacket', function(id, bs, ...)
    if id == 220 then
        raknetBitStreamIgnoreBits(bs, 8)
        local packetType = raknetBitStreamReadInt8(bs)
        if packetType == 46 then -- диалог
            raknetBitStreamIgnoreBits(bs, 72) -- 8*9
            local dialogTitleLen = raknetBitStreamReadInt16(bs)
            local dialogTitle = raknetBitStreamReadString(bs, dialogTitleLen)
            if dialogTitle:find('Администрация в сети') then
                admins = {}
                raknetBitStreamIgnoreBits(bs, 320) -- 8*40
                local dialogTextLen = raknetBitStreamReadInt16(bs)
                local dialogText = raknetBitStreamReadString(bs, dialogTextLen)
                for line in dialogText:gmatch('[^\n]+') do
                    if line:find('Заместитель Главного Администратора') then
                        goto continue
                    end
                    local rank, nickname, id, rep, state, afk = line:match('^%{FFFFFF%}(.*) ([%w_]+)%[(%d+)%]\t(%d+)\t(.*)\t(.*)$')
                    table.insert(admins, {
                        rank = rank,
                        nickname = nickname,
                        id = id,
                        rep = rep,
                        state = state,
                        afk = afk
                    })
                    ::continue::
                end
                table.sort(admins, compareRanks)
            end
        elseif packetType == 41 then
            local textLen = raknetBitStreamReadInt16(bs)
            local jsonString = raknetBitStreamReadString(bs, textLen)
            local jsonData = decodeJson(jsonString)
            if jsonData.show and jsonData.type == "REPORT_SHOW" then
                isReportShowed = jsonData.show == "admin"      
            end
        end
    end
end)
Lua:
function sampev.onShowDialog(id, style, title, button1, button2, text)
    if id == 220 then
        if title:find('Администрация в сети') then
            admins = {}
            for list in string.gmatch(text, "[^\r\n]+") do
                local rank, nickname, id, rep, state, afk = line:match('^%{FFFFFF%}(.*) ([%w_]+)%[(%d+)%]\t(%d+)\t(.*)\t(.*)$')
                table.insert(admins, {
                        rank = rank,
                        nickname = nickname,
                        id = id,
                        rep = rep,
                        state = state,
                        afk = afk
                    })
            end
            table.sort(admins, compareRanks)
            return false
        end
    end
end
 
  • Bug
Реакции: chromiusj