|
|
|
@ -29,6 +29,7 @@ function main() |
|
|
|
|
lua_thread.create(get_guns.loop) |
|
|
|
|
lua_thread.create(updateScoresAndPing) |
|
|
|
|
lua_thread.create(mafiawar.loop) |
|
|
|
|
lua_thread.create(mhcars.loop) |
|
|
|
|
while true do |
|
|
|
|
wait(0) |
|
|
|
|
live = os.time() |
|
|
|
@ -218,7 +219,25 @@ menu.update = function() |
|
|
|
|
config.save(config.data) |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
{ -->> Клавиша отправки таймингов |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Отправить тайминги в рацию\t"..convertKeysToText(config.data.chat_timing.key), |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
config.data.chat_timing.key = setKeys() |
|
|
|
|
config.save(config.data) |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Отправлять тайминги при получении |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Отправлять тайминги в рацию при проверке\t"..(config.data.chat_timing.auto and "вкл" or "выкл"), |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
config.data.chat_timing.auto = not config.data.chat_timing.auto |
|
|
|
|
config.save(config.data) |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Разделитель |
|
|
|
|
title = " \t ", |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
@ -376,23 +395,10 @@ menu.update = function() |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Клавиша инвайта |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Инвайт по кнопке\tПрицел + "..config.data.invite_helper.key:gsub("VK_", ""), |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Инвайт по кнопке\tПрицел + "..convertKeysToText(config.data.invite_helper.key), |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
wait(100) |
|
|
|
|
local key = "" |
|
|
|
|
repeat |
|
|
|
|
wait(0) |
|
|
|
|
if not sampIsDialogActive() then |
|
|
|
|
sampShowDialog(222, "Смена активации", "Нажмите на любую клавишу", "Выбрать", "Закрыть", 0) |
|
|
|
|
end |
|
|
|
|
for k, v in pairs(vkeys) do |
|
|
|
|
if wasKeyPressed(v) and k ~= "VK_ESCAPE" and k ~= "VK_RETURN" then |
|
|
|
|
key = k |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
until key ~= "" |
|
|
|
|
config.data.invite_helper.key = key |
|
|
|
|
config.data.invite_helper.key = setKeys() |
|
|
|
|
config.save(config.data) |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
@ -447,23 +453,10 @@ menu.update = function() |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Клавиша взятия ганов |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Брать оружие по кнопке\t"..config.data.get_guns.key:gsub("VK_", ""), |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Брать оружие по кнопке\t"..convertKeysToText(config.data.get_guns.key), |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
wait(100) |
|
|
|
|
local key = "" |
|
|
|
|
repeat |
|
|
|
|
wait(0) |
|
|
|
|
if not sampIsDialogActive() then |
|
|
|
|
sampShowDialog(222, "Смена активации", "Нажмите на любую клавишу", "Выбрать", "Закрыть", 0) |
|
|
|
|
end |
|
|
|
|
for k, v in pairs(vkeys) do |
|
|
|
|
if wasKeyPressed(v) and k ~= "VK_ESCAPE" and k ~= "VK_RETURN" then |
|
|
|
|
key = k |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
until key ~= "" |
|
|
|
|
config.data.get_guns.key = key |
|
|
|
|
config.data.get_guns.key = setKeys() |
|
|
|
|
config.save(config.data) |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
@ -490,7 +483,7 @@ menu.update = function() |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Mafiawar |
|
|
|
|
title = "{"..config.data.font.color1.."}".."Автоматический mafiawar\t", |
|
|
|
|
title = "{"..config.data.font.color1.."}".."Забив\t", |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
@ -539,6 +532,74 @@ menu.update = function() |
|
|
|
|
end, config.data.mafiawar.wait, "Введите задержку для флудера mafiawar в ms"} |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Разделитель |
|
|
|
|
title = " \t ", |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Mhcars |
|
|
|
|
title = "{"..config.data.font.color1.."}".."Перегон\t", |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Mhcars auto |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Флудер перегона\t"..(config.data.mhcars.auto and "вкл" or "выкл"), |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
config.data.mhcars.auto = not config.data.mhcars.auto |
|
|
|
|
config.save(config.data) |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Кому перегон |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Кому\t"..config.data.mhcars.gang, |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
menu.show = { true, "edit", function(button, list, input, outs) |
|
|
|
|
if button == 1 then |
|
|
|
|
if #input > 0 then |
|
|
|
|
config.data.mhcars.gang = input |
|
|
|
|
config.save(config.data) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end, config.data.mhcars.gang, "Введите название банды\n\tgrove\n\tballas\n\tvagos\n\trifa\n\taztec"} |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Таймер перегон |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Задержка флуда\t"..config.data.mhcars.wait.." ms", |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
menu.show = { true, "edit", function(button, list, input, outs) |
|
|
|
|
if button == 1 then |
|
|
|
|
if input:find("(%d+)") then |
|
|
|
|
config.data.mhcars.wait = tonumber(input:match("(%d+)")) |
|
|
|
|
config.save(config.data) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end, config.data.mhcars.wait, "Введите задержку для флудера mhcars в ms"} |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
{ -->> Начать флудить раньше на сек |
|
|
|
|
title = "{"..config.data.font.color1.."}"..">{ffffff} Флудить раньше на\t"..config.data.mhcars.offset_wait.." sec", |
|
|
|
|
click = function(button, list, input , outs) |
|
|
|
|
if button ~= 1 then return end |
|
|
|
|
menu.show = { true, "edit", function(button, list, input, outs) |
|
|
|
|
if button == 1 then |
|
|
|
|
if input:find("(%d+)") then |
|
|
|
|
config.data.mhcars.offset_wait = tonumber(input:match("(%d+)")) |
|
|
|
|
config.save(config.data) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
menu.show = { true, "main" } |
|
|
|
|
end, config.data.mhcars.offset_wait, "Введите на сколько секунд раньше нужно начать флудить"} |
|
|
|
|
end |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
["edit"] = { |
|
|
|
@ -713,6 +774,52 @@ menu.loop = function() |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-->> MHCARS |
|
|
|
|
mhcars = {} |
|
|
|
|
mhcars.time = 0 |
|
|
|
|
mhcars.onServerMessage = function(color, message) |
|
|
|
|
if message == " Задание уже начато" then |
|
|
|
|
mhcars.time = os.time() + 1800 |
|
|
|
|
end |
|
|
|
|
if message == " Задание по перегону машин завершено" then |
|
|
|
|
mhcars.time = 0 |
|
|
|
|
end |
|
|
|
|
if message:find("^ Задание будет доступно через: ") then |
|
|
|
|
local p1, p2, p3 = string.match(message, "Задание будет доступно через: (%d+):(%d+):(%d+)") |
|
|
|
|
if(p3 == nil)then |
|
|
|
|
p1, p2 = string.match(message, "Задание будет доступно через: (%d+):(%d+)") |
|
|
|
|
end |
|
|
|
|
if(p1 ~= nil and p2 ~= nil)then |
|
|
|
|
local mhTimer = 0 |
|
|
|
|
if(p3 ~= nil)then |
|
|
|
|
mhTimer = tonumber(p1) * 3600 |
|
|
|
|
mhTimer = mhTimer + (tonumber(p2) * 60) |
|
|
|
|
mhTimer = mhTimer + tonumber(p3) |
|
|
|
|
else |
|
|
|
|
mhTimer = mhTimer + (tonumber(p1) * 60) |
|
|
|
|
mhTimer = mhTimer + tonumber(p2) |
|
|
|
|
end |
|
|
|
|
mhcars.time = os.time() + mhTimer - config.data.mhcars.offset_wait |
|
|
|
|
end |
|
|
|
|
end --> by Richard_Holmes |
|
|
|
|
end |
|
|
|
|
mhcars.loop = function() |
|
|
|
|
while true do |
|
|
|
|
wait(0) |
|
|
|
|
if mhcars.time == 0 then |
|
|
|
|
if mhcars.antiflood == nil or os.time() - mhcars.antiflood > 1 then |
|
|
|
|
mhcars.antiflood = os.time() |
|
|
|
|
antiflood.send[#antiflood.send+1] = "/mhcars "..config.data.mhcars.gang |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if mhcars.time ~= 0 and os.time() > mhcars.time then |
|
|
|
|
if antiflood.get() > config.data.mhcars.wait then |
|
|
|
|
sampSendChat("/mhcars "..config.data.mhcars.gang) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-->> MAFIAWAR |
|
|
|
|
mafiawar = {} |
|
|
|
|
mafiawar.id = -1 |
|
|
|
@ -783,7 +890,7 @@ mafiawar.loop = function() |
|
|
|
|
antiflood.send[#antiflood.send+1] = "/mafiawar "..config.data.mafiawar.id |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if mafiawar.time ~= 0 and os.time() > mafiawar.time then |
|
|
|
|
if mafiawar.time ~= 0 and os.time() >= mafiawar.time then |
|
|
|
|
if antiflood.get() > config.data.mafiawar.wait then |
|
|
|
|
sampSendChat("/mafiawar "..config.data.mafiawar.id) |
|
|
|
|
end |
|
|
|
@ -920,10 +1027,10 @@ get_guns.loop = function() |
|
|
|
|
antiflood.send[#antiflood.send+1] = "/warehouse" |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if get_guns.enter_textdraw and isKeyCanBePressed() and wasKeyPressed(vkeys[config.data.get_guns.key]) and not get_guns.getgun then |
|
|
|
|
if get_guns.enter_textdraw and isKeyCanBePressed() and isKeysPressed(config.data.get_guns.key) and not get_guns.getgun then |
|
|
|
|
get_guns.start_get() |
|
|
|
|
else |
|
|
|
|
if wasKeyPressed(vkeys[config.data.get_guns.key]) and get_guns.getgun then |
|
|
|
|
if isKeysPressed(config.data.get_guns.key) and get_guns.getgun then |
|
|
|
|
msg.add("Выполняется взятие ганов") |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
@ -1042,7 +1149,7 @@ invite_helper.loop = function() |
|
|
|
|
local result, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) |
|
|
|
|
if result then |
|
|
|
|
local result, id = sampGetPlayerIdByCharHandle(ped) |
|
|
|
|
if result and wasKeyPressed(vkeys[config.data.invite_helper.key]) then |
|
|
|
|
if result and isKeysPressed(config.data.invite_helper.key) then |
|
|
|
|
antiflood.send[#antiflood.send+1] = "/invite "..id |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
@ -1247,11 +1354,16 @@ ammo_timer.onServerMessage = function(color, message) |
|
|
|
|
end |
|
|
|
|
if message:find("^ Следующее ограбление будет доступно в (%d+:%d+:%d+)") then |
|
|
|
|
if ammo_timer.last_ammo ~= "" then |
|
|
|
|
local text = message:match("^ Следующее ограбление будет доступно в (%d+:%d+:%d+)") |
|
|
|
|
request.send[#request.send + 1] = { |
|
|
|
|
key = ammo_timer.last_ammo, |
|
|
|
|
text = message:match("^ Следующее ограбление будет доступно в (%d+:%d+:%d+)") |
|
|
|
|
text = text |
|
|
|
|
} |
|
|
|
|
request.wait = 0 |
|
|
|
|
if config.data.chat_timing.auto then |
|
|
|
|
msg.add("/r "..ammo_timer.last_ammo:upper()..": "..text) |
|
|
|
|
antiflood.send[#antiflood.send + 1] = "/r "..ammo_timer.last_ammo:upper()..": "..text |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if message:find("^ Задание будет доступно через: ") then |
|
|
|
@ -1293,19 +1405,31 @@ ammo_timer.data = { |
|
|
|
|
} |
|
|
|
|
ammo_timer.loop = function() |
|
|
|
|
font = renderCreateFont(config.data.font.name,config.data.font.size,config.data.font.flag) |
|
|
|
|
local getText = function(key) |
|
|
|
|
local getText = function(key, oneline) |
|
|
|
|
if config.data.timer_hud[key] ~= nil and not config.data.timer_hud[key] then |
|
|
|
|
return "" |
|
|
|
|
end |
|
|
|
|
if ammo_timer.data[key]["time"] == 0 then |
|
|
|
|
return string.format("{%s}%s:{%s} %s\n", config.data.font.color1, key:upper(), config.data.font.color2, ammo_timer.data[key]["text"]) |
|
|
|
|
if oneline == nil then |
|
|
|
|
return string.format("{%s}%s:{%s} %s\n", config.data.font.color1, key:upper(), config.data.font.color2, ammo_timer.data[key]["text"]) |
|
|
|
|
else |
|
|
|
|
return string.format("%s: %s", key:upper(), ammo_timer.data[key]["text"]) |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
local min = math.floor((msk_time.get() - ammo_timer.data[key]["time"]) / 60) |
|
|
|
|
return string.format("{%s}%s:{%s} %s (%d min)\n", config.data.font.color1, key:upper(), config.data.font.color2, ammo_timer.data[key]["text"], min) |
|
|
|
|
if oneline == nil then |
|
|
|
|
return string.format("{%s}%s:{%s} %s (%d min)\n", config.data.font.color1, key:upper(), config.data.font.color2, ammo_timer.data[key]["text"], min) |
|
|
|
|
else |
|
|
|
|
return string.format("%s: %s (%d min)", key:upper(), ammo_timer.data[key]["text"], min) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
while true do |
|
|
|
|
wait(0) |
|
|
|
|
if isKeyCanBePressed() and isKeysPressed(config.data.chat_timing.key) then |
|
|
|
|
local text = string.format("/r %s %s %s", getText("ls", 1), getText("sf", 1), getText("lv", 1)) |
|
|
|
|
antiflood.send[#antiflood.send+1] = text |
|
|
|
|
end |
|
|
|
|
if config.data.timer_hud.main then |
|
|
|
|
if ammo_timer.setpos then |
|
|
|
|
sampSetCursorMode(3) |
|
|
|
@ -1387,7 +1511,7 @@ config.default = { |
|
|
|
|
lvl = 7, |
|
|
|
|
auto_rank = true, |
|
|
|
|
rank = 7, |
|
|
|
|
key = "VK_I", |
|
|
|
|
key = { "VK_I" }, |
|
|
|
|
message = "Добро пожаловать, {name}!" |
|
|
|
|
}, |
|
|
|
|
get_guns = { |
|
|
|
@ -1400,12 +1524,15 @@ config.default = { |
|
|
|
|
{ "Rifle", 0, 6, 10 }, |
|
|
|
|
{ "Броня", 0, 777, 10 } |
|
|
|
|
}, |
|
|
|
|
key = "VK_G", |
|
|
|
|
key = { "VK_G" }, |
|
|
|
|
auto_get_guns = false, |
|
|
|
|
warelock_auto = false, |
|
|
|
|
warelock_text = { |
|
|
|
|
"sklad", |
|
|
|
|
"склад" |
|
|
|
|
"склад", |
|
|
|
|
"wl", |
|
|
|
|
"warelock", |
|
|
|
|
"/warelock" |
|
|
|
|
}, |
|
|
|
|
warelock_time = 5 |
|
|
|
|
}, |
|
|
|
@ -1421,6 +1548,16 @@ config.default = { |
|
|
|
|
auto = true, |
|
|
|
|
id = 0, |
|
|
|
|
wait = 600 |
|
|
|
|
}, |
|
|
|
|
chat_timing = { |
|
|
|
|
key = { "VK_MENU", "VK_A" }, |
|
|
|
|
auto = true |
|
|
|
|
}, |
|
|
|
|
mhcars = { |
|
|
|
|
auto = true, |
|
|
|
|
gang = "grove", |
|
|
|
|
wait = 200, |
|
|
|
|
offset_wait = 1 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
config.directory = string.format("%s\\moonloader\\config\\%s\\", getGameDirectory(), thisScript().name) |
|
|
|
@ -1445,6 +1582,9 @@ config.init = function() |
|
|
|
|
if config.data[k][kk] == nil then |
|
|
|
|
config.data[k][kk] = vv |
|
|
|
|
end |
|
|
|
|
if type(vv) ~= type(config.data[k][kk]) then |
|
|
|
|
config.data[k][kk] = vv |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
@ -1504,14 +1644,12 @@ function sampev.onServerMessage(color, message) |
|
|
|
|
timer_2min.onServerMessage(color, message) |
|
|
|
|
ammo_timer.onServerMessage(color, message) |
|
|
|
|
invite_helper.onServerMessage(color, message) |
|
|
|
|
mafiawar.onServerMessage(color, message) |
|
|
|
|
mhcars.onServerMessage(color, message) |
|
|
|
|
local res = processEvent(get_guns.onServerMessage, table.pack(color, message)) |
|
|
|
|
if res then |
|
|
|
|
return table.unpack(res) |
|
|
|
|
end |
|
|
|
|
local res = processEvent(mafiawar.onServerMessage, table.pack(color, message)) |
|
|
|
|
if res then |
|
|
|
|
return table.unpack(res) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
function sampev.onSendPickedUpPickup(id) |
|
|
|
@ -1722,6 +1860,57 @@ function sendRpcCommand(text) |
|
|
|
|
raknetSendRpc(50,bs) |
|
|
|
|
raknetDeleteBitStream(bs) |
|
|
|
|
end |
|
|
|
|
function convertKeysToText(arr) |
|
|
|
|
local text = "" |
|
|
|
|
for i = 1, #arr do |
|
|
|
|
text = string.format("%s%s%s", text, arr[i]:gsub("VK_", ""), (i == #arr and "" or " + ")) |
|
|
|
|
end |
|
|
|
|
return text |
|
|
|
|
end |
|
|
|
|
function isKeysPressed(arr) |
|
|
|
|
local result = 0 |
|
|
|
|
for i = 1, #arr do |
|
|
|
|
if i == #arr then |
|
|
|
|
if wasKeyPressed(vkeys[arr[i]]) then |
|
|
|
|
result = result + 1 |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
if isKeyDown(vkeys[arr[i]]) then |
|
|
|
|
result = result + 1 |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if result == #arr then |
|
|
|
|
return true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
function setKeys() |
|
|
|
|
wait(100) |
|
|
|
|
local key_combo = {} |
|
|
|
|
repeat |
|
|
|
|
wait(0) |
|
|
|
|
if not sampIsDialogActive() then |
|
|
|
|
sampShowDialog(222, "Смена активации", "Зажмите нужное сочетание клавиш и отпустите для сохранения!", "Выбрать", "Закрыть", 0) |
|
|
|
|
end |
|
|
|
|
local isPress = false |
|
|
|
|
for k, v in pairs(vkeys) do |
|
|
|
|
if isKeyDown(v) and k ~= "VK_ESCAPE" and k ~= "VK_RETURN" then |
|
|
|
|
local isKeyFind = false |
|
|
|
|
for i = 1, #key_combo do |
|
|
|
|
if key_combo[i] == k then |
|
|
|
|
isKeyFind = true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if not isKeyFind then |
|
|
|
|
key_combo[#key_combo+1] = k |
|
|
|
|
end |
|
|
|
|
isPress = true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
printStringNow(convertKeysToText(key_combo), 1) |
|
|
|
|
until #key_combo > 0 and not isPress |
|
|
|
|
return key_combo |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-->> UPDATE MODULE |
|
|
|
|
function openURL(url, fpath, message_off) |
|
|
|
|