Всем привет! Меня зовут Vintik.
Сегодня я буду рассказывать, как делать скрипт «Быстрый звонок Arizona-RP(G)». Суть далеко не в исходнике, а, скорее, для новичков, которые хотят познакомиться с синтаксисом этого языка программирования и параллельно научиться создавать реальные скрипты (не в одну строчку).
Начать стоит с самого начального кода (можно назвать "шапкой"), с которым мы будем в дальнейшем работать. Кодировку скрипта не забудьте указать – Windows 1251.
Сегодня я буду рассказывать, как делать скрипт «Быстрый звонок Arizona-RP(G)». Суть далеко не в исходнике, а, скорее, для новичков, которые хотят познакомиться с синтаксисом этого языка программирования и параллельно научиться создавать реальные скрипты (не в одну строчку).
Начать стоит с самого начального кода (можно назвать "шапкой"), с которым мы будем в дальнейшем работать. Кодировку скрипта не забудьте указать – Windows 1251.
Lua:
require 'lib.moonloader' -- подключение стандартных библиотек
require 'sampfuncs' -- для работы с SAMP функциями
local sampev = require 'lib.samp.events' -- модуль SAMP.Lua
function main()
if not isSampLoaded() and not isSampfuncsLoaded() then return end -- если самп не загружен – выгружаем скрипт
while not isSampAvailable() do wait(0) end -- ждём, пока пройдёт меню загрузки
end
Модуль SAMP.Events необходим для того, чтобы работать с коллбэками, что мы будем делать позже. Да, кстати, в LUA "--" комментирует всё после этих двух символов (это никак не влияет на программу, просто пометки для разработчика). После каждого обновления кода, чтобы не перезаходить в игру, просто нажмите Ctrl + R, если у вас установлен перезапускатель скриптов (если нет – добавлю его в конец статьи, сразу скачайте и закиньте в папку moonloader).
Первым делом стоит "зарегистрировать" команду /call (то есть сделать так, чтобы при вводе такой команды скрипт реагировал и делал какие-то действия).
Первым делом стоит "зарегистрировать" команду /call (то есть сделать так, чтобы при вводе такой команды скрипт реагировал и делал какие-то действия).
Lua:
require 'lib.moonloader' -- подключение стандартных библиотек
require 'sampfuncs' -- для работы с SAMP функциями
local sampev = require 'lib.samp.events' -- модуль SAMP.Lua
function main()
if not isSampLoaded() and not isSampfuncsLoaded() then return end -- если самп не загружен – выгружаем скрипт
while not isSampAvailable() do wait(0) end -- ждём, пока пройдёт меню загрузки
sampRegisterChatCommand('call', phone) -- "регистрация" команды. первым аргументом функции является сама команда (без /), вторым – функция, которая вызывается при её написании
end
function phone(arg) -- вот и сама функция, которая будет вызывать тогда, когда мы пишем /call
sampAddChatMessage(arg, -1) -- для теста будем писать в чат аргумент этой функции (то, что после /call)
-- например при вводе: /call hello world
-- в чат выведет: hello world
end
Работает? Тогда удаляем написание сообщения в чат. Теперь давайте не отклоняться от нашей темы. При вводе /call первым делом надо достать телефон, написав команду в чат "/phone". После этого в открывшемся диалоге выбрать первый (или любой другой) телефон.
Для начала надо узнать title (заголовок) диалога, который открывается. Для этого в конец кода добавим такой кусок:
Для начала надо узнать title (заголовок) диалога, который открывается. Для этого в конец кода добавим такой кусок:
Lua:
function sampev.onShowDialog(dialogId, style, title, button1, button2, text) -- вот и модуль SAMP.Events. эта функция будет вызываться тогда, когда откроется диалог
sampAddChatMessage(title, -1) -- отправляем в чат заголовок диалога. -1 – это цвет строки, в данном случае (-1) это белый
end
Теперь, чтобы скопировать строку из чата (от руки переписывать строку НЕ НАДО, потому что она разноцветная – сейчас поймете), заходим в "Мои документы", "GTA San Andreas User Files", "SAMP", "chatlog". Листаем в конец и находим эту строку, вот она:
Видите {...}? Это так задаётся цвет в строке, теперь понятно, что от руки никто бы не переписал заголовок диалогу (который мы вывели в чат). Теперь кидаю вам обновленный код:{BFBBBA}{FFFFFF}Телефоны | {ae433d}Телефоны
Lua:
require 'lib.moonloader' -- подключение стандартных библиотек
require 'sampfuncs' -- для работы с SAMP функциями
local sampev = require 'lib.samp.events' -- модуль SAMP.Lua
function main()
if not isSampLoaded() and not isSampfuncsLoaded() then return end -- если самп не загружен – выгружаем скрипт
while not isSampAvailable() do wait(0) end -- ждём, пока пройдёт меню загрузки
sampRegisterChatCommand('call', phone) -- "регистрация" команды. первым аргументом функции является сама команда (без /), вторым – функция, которая вызывается при её написании
end
function phone(arg) -- вот и сама функция, которая будет вызывать тогда, когда мы пишем /call
sampSendChat('/phone') -- пишем в чат
end
function sampev.onShowDialog(dialogId, style, title, button1, button2, text) -- вот и модуль SAMP.Events. эта функция будет вызываться тогда, когда откроется диалог
if title == '{BFBBBA}{FFFFFF}Телефоны | {ae433d}Телефоны' then -- если у диалога такой заголовок (то бишь это нужный нам диалог)
sampSendDialogResponse(dialogId, 1, 0, nil) -- закрываем диалог первой (левой) кнопкой с выбранным 1 пунктом (нумерация пунктов с нуля, поэтому типо "нулевой")
return false -- запрещаем диалогу визуально показываться на экран (иначе он останется открытым).
end
end
Вроде работает, скажите Вы. Но нет! Он закрывать диалог должен только в случае, если его вызвал скрипт, вдруг Вы хотите воспользоваться телефоном самостоятельно и выбрать другой мобильный аппарат? Надо сделать проверку.
Перед main() добавляем:
После sampSendChat('/phone') добавляем:
И перед return false тоже добавляем:
Теперь можете проверить. Если пишите /phone – диалог остаётся, если пишите /call – сразу выбирается первый телефон. То что надо!
Начинается самое важное и моё нелюбимое: работа с текстдравами. Придётся. Нужно узнать ID текстдрава, который является значком "Позвонить". Для этого в конец кода добавляем:
Перед main() добавляем:
Lua:
local phoneDialog = false -- глобальная переменная (работает во всех функциях). true - если след. диалог вызван скриптом
Lua:
phoneDialog = true -- говорим, что следующий диалог вызван скриптом
Lua:
phoneDialog = false -- говорим, что след. диалог будет вызван не скриптом.
Начинается самое важное и моё нелюбимое: работа с текстдравами. Придётся. Нужно узнать ID текстдрава, который является значком "Позвонить". Для этого в конец кода добавляем:
Lua:
function sampev.onSendClickTextDraw(id) -- когда мы кликаем по текстдраву
sampAddChatMessage(id, -1) -- выписываем его id в чат
end
Теперь перезагружаем скрипт и пишем в чат /call, затем нажимаем на значок позвонить – в чат добавляется цифра "2098", и это ID нужного нам текстдрава. Отлично! Теперь нужно реализовать нажатие на этот текстдрав (извините за тавтологию, это слово никак не заменить) с помощью скрипта.
Первым делом удалим "отладочный" код, который я написал последним, затем после local phoneDialog = false добавим:
А после phoneDialog = false добавим:
Ну и в конец кода добавляем:
Первым делом удалим "отладочный" код, который я написал последним, затем после local phoneDialog = false добавим:
Lua:
local callTextdraw = false
Lua:
callTextdraw = true
Lua:
function sampev.onShowTextDraw(id, data) -- когда появляется любой текстдрав
if id == 2098 and callTextdraw then -- если он вызван нашим скриптом и если это нужный нам текстдрав
callTextdraw = false
sampSendClickTextdraw(id) -- говорим, что мы кликнули по текстдраву
numberTextdraw = true
end
end
Теперь когда мы открываем тф через /call – автоматически называется значок "Набрать номер" (ранее я его назвал "Позвонить").
Lua:
require 'lib.moonloader' -- подключение стандартных библиотек
require 'sampfuncs' -- для работы с SAMP функциями
local sampev = require 'lib.samp.events' -- модуль SAMP.Lua
local phoneDialog = false -- глобальная переменная (работает во всех функциях). true - если след. диалог вызван скриптом
local callTextdraw = false
function main()
if not isSampLoaded() and not isSampfuncsLoaded() then return end -- если самп не загружен – выгружаем скрипт
while not isSampAvailable() do wait(0) end -- ждём, пока пройдёт меню загрузки
sampRegisterChatCommand('call', phone) -- "регистрация" команды. первым аргументом функции является сама команда (без /), вторым – функция, которая вызывается при её написании
end
function phone(arg) -- вот и сама функция, которая будет вызывать тогда, когда мы пишем /call
sampSendChat('/phone') -- пишем в чат
phoneDialog = true -- говорим, что следующий диалог вызван скриптом
end
function sampev.onShowDialog(dialogId, style, title, button1, button2, text) -- вот и модуль SAMP.Events. эта функция будет вызываться тогда, когда откроется диалог
if title == '{BFBBBA}{FFFFFF}Телефоны | {ae433d}Телефоны' and phoneDialog then -- если у диалога такой заголовок (то бишь это нужный нам диалог)
-- добавляем проверку phoneDialog == true (можно просто phoneDialog)
sampSendDialogResponse(dialogId, 1, 0, nil) -- закрываем диалог первой (левой) кнопкой с выбранным 1 пунктом (нумерация пунктов с нуля, поэтому типо "нулевой")
phoneDialog = false -- говорим, что след. диалог будет вызван не скриптом.
callTextdraw = true
return false -- запрещаем диалогу визуально показываться на экран (иначе он останется открытым).
end
end
function sampev.onShowTextDraw(id, data) -- когда появляется любой текстдрав
if id == 2098 and callTextdraw then -- если он вызван нашим скриптом и если это нужный нам текстдрав
callTextdraw = false
sampSendClickTextdraw(id) -- говорим, что мы кликнули по текстдраву
end
end
Чтобы вы не терялись, буду регулярно скидывать полный код.
Далее задача немного усложняется. Надо вернуться к тому, что уже написали, и добавить кое-что: нам надо проверить, является ли аргумент команды /call неотрицательным числом (чтобы быть номером телефона). Для этого будем проходиться по всем элементам аргумента, проверяя, являются ли она числами, и затем записывать в массив.
И так, после local callTextdraw = false добавляем:
Lua:
local number = {} -- создаем массив цифр номера телефона, который набираем
{ 1, 2, 3, 4, 5, 9, 8 }
Надеюсь, усвоили.
Теперь заменяем функцию phone на вот эту (все объяснил в комментариях к строкам):
Lua:
function phone(arg) -- вот и сама функция, которая будет вызывать тогда, когда мы пишем /call
number = {} -- обнуление номера
local isNumber = true
for i = 1, string.len(arg) do -- проходимся по всем символам строки
local c = tonumber(string.sub(arg, i, i)) -- берем i-тый элемент строки, преобразуем его в число
if type(c) ~= 'number' then -- если преобразовать в число не получилось (не число, короче)
isNumber = false -- говорим, что не число
break -- заканчиваем проверку
end
number[#number + 1] = c -- в конец массива добавляем новую (следующую) цифру. и так до конца нашего аргумента
end
if isNumber and #number ~= 0 then -- если аргумент – число
sampSendChat('/phone') -- пишем в чат
phoneDialog = true -- говорим, что следующий диалог вызван скриптом
else -- если не число
sampAddChatMessage('Чтобы совершить быстрый звонок, введите /call [номер]', 0x4287f5) -- говорим юзеру как ввести команду
end
end
Теперь опять в конец добавляем код:
Lua:
function sampev.onSendClickTextDraw(id) -- когда мы кликаем по текстдраву
sampAddChatMessage('id = ' .. id, -1) -- выписываем его id в чат
end
По очереди кликаем на циферки от 0 до 9 и записываем в массив соответствующие ID-шники текстдравов. И вот я это сделал:
В конец списка (массива) я добавил ID текстдрава "Позвонить" (его id 2096).
Разумеется, я опять по аналогии после объявленных глоб. переменных сделал:
Если переменная - false, то при виде текстдравов циферок ничего не происходит. Если true - начинается набор номера из массива number.
Lua:
local textdrawlist = { 2111, 2103, 2104, 2102, 2106, 2107, 2105, 2109, 2110, 2108, 2096 } -- ид текстдравов цифер от "0" до "9" и "Позвонить"
Разумеется, я опять по аналогии после объявленных глоб. переменных сделал:
Lua:
local numberTextdraw = false
Lua:
function sampev.onShowTextDraw(id, data) -- когда появляется любой текстдрав
if id == 2098 and callTextdraw then -- если он вызван нашим скриптом и если это нужный нам текстдрав
callTextdraw = false
sampSendClickTextdraw(id) -- говорим, что мы кликнули по текстдраву
numberTextdraw = true
end
-- работаем уже с набором номера:
local textdrawlist = { 2111, 2103, 2104, 2102, 2106, 2107, 2105, 2109, 2110, 2108, 2096 } -- ид текстдравов цифер от "0" до "9" и "Позвонить"
local isNumeralsExist = true
for i = 1, 11 do -- проходимся по всем текстдравам
if not sampTextdrawIsExists(textdrawlist[i]) then -- если не существует текстдрава с какой-то цифрой (или кнопкой "Позвонить")
isNumeralsExist = false -- говорим, что нету всех цифер на экране
break -- заканчиваем проверку
end
end
if isNumeralsExist and numberTextdraw then -- если все цифры есть на экране
numberTextdraw = false
for i = 1, #number do -- вписываем номер телефона
local b = number[i] + 1 -- текущая цифра; +1 потому, что textdrawlist начинается с ID текстрава нуля, а массив начинается с элемента 1
sampSendClickTextdraw(textdrawlist[b])
end
sampSendClickTextdraw(2096) -- нажимаем позвонить
end
end
Заключение:
Я постарался доступно и пошагово объяснить, как надо делать такой скрипт. Надеюсь, что все поняли все (ну или почти все). Я обязательно буду стараться отвечать на вопросы, которые вы можете задать в этой теме.
Вот исходный код скрипта:
Я постарался доступно и пошагово объяснить, как надо делать такой скрипт. Надеюсь, что все поняли все (ну или почти все). Я обязательно буду стараться отвечать на вопросы, которые вы можете задать в этой теме.
Вот исходный код скрипта:
Lua:
script_name('Fast call Arizona RP')
script_author('Vintik')
require 'lib.moonloader' -- подключение стандартных библиотек
require 'sampfuncs' -- для работы с SAMP функциями
local sampev = require 'lib.samp.events' -- модуль SAMP.Lua
local phoneDialog = false -- глобальная переменная (работает во всех функциях). true - если след. диалог вызван скриптом
local callTextdraw = false
local numberTextdraw = false
local number = {} -- создаем массив цифр номера телефона, который набираем
function main()
if not isSampLoaded() and not isSampfuncsLoaded() then return end -- если самп не загружен – выгружаем скрипт
while not isSampAvailable() do wait(0) end -- ждём, пока пройдёт меню загрузки
sampRegisterChatCommand('call', phone) -- "регистрация" команды. первым аргументом функции является сама команда (без /), вторым – функция, которая вызывается при её написании
end
function phone(arg) -- вот и сама функция, которая будет вызывать тогда, когда мы пишем /call
number = {} -- обнуление номера
local isNumber = true
for i = 1, string.len(arg) do -- проходимся по всем символам строки
local c = tonumber(string.sub(arg, i, i)) -- берем i-тый элемент строки, преобразуем его в число
if type(c) ~= 'number' then -- если преобразовать в число не получилось (не число, короче)
isNumber = false -- говорим, что не число
break -- заканчиваем проверку
end
number[#number + 1] = c -- в конец массива добавляем новую (следующую) цифру. и так до конца нашего аргумента
end
if isNumber and #number ~= 0 then -- если аргумент – число
sampSendChat('/phone') -- пишем в чат
phoneDialog = true -- говорим, что следующий диалог вызван скриптом
else -- если не число
sampAddChatMessage('Чтобы совершить быстрый звонок, введите /call [номер]', 0x4287f5) -- говорим юзеру как ввести команду
end
end
function sampev.onShowDialog(dialogId, style, title, button1, button2, text) -- вот и модуль SAMP.Events. эта функция будет вызываться тогда, когда откроется диалог
if title == '{BFBBBA}{FFFFFF}Телефоны | {ae433d}Телефоны' and phoneDialog then -- если у диалога такой заголовок (то бишь это нужный нам диалог)
-- добавляем проверку phoneDialog == true (можно просто phoneDialog)
sampSendDialogResponse(dialogId, 1, 0, nil) -- закрываем диалог первой (левой) кнопкой с выбранным 1 пунктом (нумерация пунктов с нуля, поэтому типо "нулевой")
phoneDialog = false -- говорим, что след. диалог будет вызван не скриптом.
callTextdraw = true
return false -- запрещаем диалогу визуально показываться на экран (иначе он останется открытым).
end
end
function sampev.onShowTextDraw(id, data) -- когда появляется любой текстдрав
if id == 2098 and callTextdraw then -- если он вызван нашим скриптом и если это нужный нам текстдрав
callTextdraw = false
sampSendClickTextdraw(id) -- говорим, что мы кликнули по текстдраву
numberTextdraw = true
end
-- работаем уже с набором номера:
local textdrawlist = { 2111, 2103, 2104, 2102, 2106, 2107, 2105, 2109, 2110, 2108, 2096 } -- ид текстдравов цифер от "0" до "9" и "Позвонить"
local isNumeralsExist = true
for i = 1, 11 do -- проходимся по всем текстдравам
if not sampTextdrawIsExists(textdrawlist[i]) then -- если не существует текстдрава с какой-то цифрой (или кнопкой "Позвонить")
isNumeralsExist = false -- говорим, что нету всех цифер на экране
break -- заканчиваем проверку
end
end
if isNumeralsExist and numberTextdraw then -- если все цифры есть на экране
numberTextdraw = false
for i = 1, #number do -- вписываем номер телефона
local b = number[i] + 1 -- текущая цифра; +1 потому, что textdrawlist начинается с ID текстрава нуля, а массив начинается с элемента 1
sampSendClickTextdraw(textdrawlist[b])
end
sampSendClickTextdraw(2096) -- нажимаем позвонить
end
end
Естественно, я даю право на свободное использование этого кода в своих скриптах, но с указанием авторства. На БХ вроде бы нету таких же скриптов с открытым кодом (а не .luac). Ну а кому нужен лишь скрипт – будет прикреплён к сообщению. Так же прикрепляю тот скрипт, который упоминал в теме – "перезагружатор скриптов на Ctrl + R", автором которого является @FYP
Все, всем пока! Спасибо, что прочитали эту статью.
P. S. У меня в коде никогда не было так много комментов
Все, всем пока! Спасибо, что прочитали эту статью.
P. S. У меня в коде никогда не было так много комментов