Функции в Lua и квестах

Функции позволяют выполнять определенный набор или последовательность действий. Основное назначение встроенных функций — это совершение уникальных действий, а назначение самопальных функций — возможность сократить количество кода, пакуя повторящийся код в функции.

Встроенные функции

Основное назначение квестов — это использование квестовых функций. Квестовые функции вшиты в ядро сервера и могут сообщать ту или иную информацию. Например, функция pc.get_name() сообщает имя игрока:

-- Lua - 0.005 s. (94.64 KB/s)
quest example begin state start begin --[[ Если ник игрока "terron", то представить в своей голове данную строку можно так:   when login with "terron" == "terron" begin   Вместо функции как бы подставляется значение, которое она сообщает. ]] when login with pc.get_name() == "terron" begin syschat("Привет, terron! ") end end end

На самом деле, правильнее говорить не «сообщают», а «возвращают», поэтому дальше мы будем придерживаться именно этого термина.

Встроенные функции могут возвращать данные любого типа. Вот несколько примеров:

-- Lua - 0.003 s. (231.73 KB/s)
quest example begin state start begin when login begin syschat("Привет, " .. pc.get_name() .. "! ") syschat("Ваш уровень - " .. pc.get_level()) -- сообщает уровень игрока (тип number) syschat("Ваш баланс - " .. pc.get_gold() .. " янг. ") -- сообщает количество янг игрока (тип number)   if pc.is_gm() then -- сообщает, является ли игрок администратором (тип boolean) syschat("Хорошего рабочего дня, уважаемый администратор! ") else syschat("Отличного фарма и удачи, уважаемый игрок! ") end end end end

Также с помощью квестовых функций можно менять информацию об игроке. В данном примере мы при каждом входе в игру функцией pc.change_gold() будем увеличивать баланс янг игрока на 500:

-- Lua - 0.003 s. (98.27 KB/s)
quest example begin state start begin when login begin local gold = 500   syschat("Привет, " .. pc.get_name() .. "! Вам было начислено " .. gold .. " за то, что вы крутой! ")   pc.change_gold(gold) end end end

Т.к. функция pc.change_gold() ничего не возвращает, то бишь возвращает nil (вы не забыли, что nil — это «ничего» или просто «пустота»?), то заключать ее в переменную или объединять с какой-либо строкой смысла нет. Она просто меняет баланс игрока и всё.

Мы передали в данную функцию число 500 как параметр. Функции могут принимать так называемые параметры (также известны как «аргументы»). Параметры заключаются в скобки, идущие после названия функции. Если параметров несколько, то они разделяются запятыми:

-- Lua - 0.003 s. (191.12 KB/s)
quest example begin state start begin when login begin syschat("Привет, " .. pc.get_name() .. "! Вы получили 5 красных зелий за то, что вы крутой! ")   --[[ 27001 - это vnum красного зелья 5 - это количество ]]   pc.give_item2(27001, 5) -- данная функция выдает игроку определенный предмет в определенном количестве end end end

Некоторые функции возвращают не одно, а несколько значений. Это одна из особенностей языка Lua. Правда, подобных встроенных функций очень мало. Например, функция pc.get_start_location() сообщает индекс локации и координаты площади первого города игрока в зависимости от его империи. Работать с такими функциями нужно так:

-- Lua - 0.005 s. (78.44 KB/s)
quest example begin state start begin when login begin local index, coordinate_x, coordinate_y = pc.get_start_location()   syschat("Индекс вашего первого города: " .. index) syschat("Координата по оси X: " .. coordinate_x) syschat("Координата по оси Y: " .. coordinate_y) end end end

Подробнее о том, сколько значений и вообще что возвращает функция, можно узнать из статьи о ней — на этом сайте задокументировано большинство квестовых функций.

Самопальные функции

Вы можете самостоятельно создавать функции в Lua, например, чтобы не писать один и тот же код по несколько раз. Самый простой способ создать функцию:

-- Lua - 0.004 s. (54.01 KB/s)
quest example begin state start begin function calculate_ab(a, b) return a + b end   when login begin local beer, vodka = 500, 800 syschat(example.calculate_ab(beer, vodka)) --> 1300 end end end

Правила именования функций такие же, как у переменных, ведь функции тоже являются переменными, просто вместо числел и строк они хранят в себе тип данных function. Внутри квестов функции могут задаваться только внутри state.

В примере выше мы задали функцию внутри state. Когда функция задается внутри state, то при ее вызове обязательно надо указывать перед ней название квеста (example.calculate_ab()). Область видимости у функций ограничивается всем квестом, независимо от того, в какой стадии была задана функция:

-- Lua - 0.005 s. (105.68 KB/s)
--[[ При каждом входе в игру игрок будет видеть разные сообщения: ]]   quest example begin state start begin function calculate_ab(a, b) return a + b end   when login begin syschat("Start: " .. example.calculate_ab(1, 2)) --> Start 3   set_state("test") end end   state test begin when login begin syschat("Test: " .. example.calculate_ab(3, 4)) --> Test 7   set_state("start") end end end

Функции создаются при помощи ключевого слова function. После ключевого слова идет название функции и в скобках заключаются параметры функции. Параметры указываются как переменные и область видимости у этих переменных будет локальной только внутри функции. Наша функция calculate_ab принимает 2 числа и считает их, а затем возвращает значение ключевым словом return. Код, идущий внутри секции ниже return, уже не исполняется:

-- Lua - 0.004 s. (101.74 KB/s)
quest example begin state start begin function calculate_ab(a, b) local val = a + b   return val   syschat("Посчитали и вот: " .. val) -- данное сообщение мы не увидим, т.к. выполнение секции закончилось на return end   when login begin local beer, vodka = 500, 800 syschat(example.calculate_ab(beer, vodka)) --> 1300 end end end

Если не передавать в return каких-либо значений, то функция ничего не вернет, то бишь nil:

-- Lua - 0.004 s. (163.02 KB/s)
quest example begin state start begin function calculate_ab(a, b) local val = a + b   syschat("Посчитали и вот: " .. val)   return   syschat("Второе сообщение... ") -- это сообщение мы не увидим end   when login begin local beer, vodka = 500, 800   local how_much = example.calculate_ab(beer, vodka) -- в этот момент появится сообщение "Посчитали и вот: 1300", так как в этот момент исполняется функция calculate_ab()   if how_much then syschat(how_much) -- мы не увидим это сообщение т.к. how_much == nil end end end end

В отличие от оригинального Lua, внутри квестов динамически создавать функции через переменные нельзя. Зато функции можно создавать глобально. Глобальные функции можно будет использовать во всех квестах, а не только в том, в котором она была создана. Такие функции создаются в файле questlib.lua. Особенность этого файла в том, что код, находящийся в нем, исполняется только один раз во время запуска сервера. То есть мы объявляем в этом файле функцию один раз, файл запускается сервером один раз и на время работы сервера он будет помнить о том, что существуют такие-то функции и переменные, заданные в questlib.lua. Добавьте в самый конец файла нашу функцию:

-- Lua - 0.004 s. (17.82 KB/s)
function calculate_ab(a, b) local val = a + b   return val end

Также функции в questlib.lua можно задавать как переменные (а в самих квестах нельзя!). Результат данного примера будет идентичен примеру выше:

-- Lua - 0.004 s. (19.68 KB/s)
local calculate_ab = function(a, b) local val = a + b   return val end

И чтобы функция начала работать в квестах, ее необходимо добавить в файл quest_functions (без расширения). Просто в конец файла добавьте calculate_ab и всё. Не забудьте про то, что последние строки в файлах должны быть пустыми! Теперь нашу функцию можно использовать в квестах:

-- Lua - 0.004 s. (39.09 KB/s)
quest example begin state start begin when login begin local beer, vodka = 500, 800   syschat(calculate_ab(beer, vodka)) --> 1300 end end end

Обратите внимание на то, что при использовании функций, заданных глобально, использовать приставку в виде названия квеста не нужно.

195