Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
543 lines (388 sloc) 25.1 KB

Основы Lua

В данной статье будут рассмотрены основные и наиболее простые для понимания возможности Lua.

Условные операторы

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

Начнем с простого примера:

if 10 > 5 then
	syschat("горошек ")
end

Понять это можно так: если 10 больше 5, тогда отправляем сообщение в чат слово «горошек». Другими словами, если между if и then выражение является истиной (true), то будут выполнены соответствующие инструкции. Ключевое слово end закрывает управляющие конструкции. Управляющая конструкция — это всё, что находится между if и end.

Более сложный пример:

if 5 > 10 then
	syschat("горошек ") -- это сообщение мы не увидим
else
	syschat("кукуруза ") -- мы увидим это сообщение
end

В данном примере я поменял числа местами и расширил управляющую конструкцию секцией else. Данное ключевое слово переводится как «иначе». Данная секция содержит инструкции, которые будут исполнены в случае, если условия идущих ранее секций являются ложью. Грубо говоря, мы в секции с if проверяем, больше ли 5 чем 10. Разумеется, это ложь (false), поэтому выполняется секция else.

И третий пример:

if 5 > 10 then
	syschat("горошек ") -- это сообщение мы не увидим
elseif 5 > 1 then
	syschat("пюрешечка ") -- мы увидим это сообщение
else
	syschat("кукуруза ") -- это сообщение мы не увидим
end

Я использовал оператор elseif. Данный оператор является некой смесью операторов if и else. Он выполняется в случае, если условия идущих ранее секций являются ложью, но только в том случае, если его условие является истиной. Если его условие было бы ложью, то выполнилась бы секция else.

Во всей управляющей конструкции (от if до end) может быть выполнена только одна секция. Если у вас несколько секций, то выполнена будет только первая из них, условия которой являются истиной:

if 5 > 10 then
	syschat("горошек ") -- это сообщение мы не увидим
elseif 5 > 1 then
	syschat("пюрешечка ") -- мы увидим это сообщение
elseif 5 > 2 then
	syschat("котлетки ") -- это сообщение мы не увидим
else
	syschat("кукуруза ") -- это сообщение мы не увидим
end

Операторы сравнения

В Lua существует несколько операторов сравнения:

Оператор Назначение
== равно
> больше
< меньше
>= больше или равно
<= меньше или равно
~= не равно
!= не равно

Оператор != является синонимом оператора ~=. Более того, оператор != отсутствует в оригинальном Lua. Также обратите внимание на то, что оператор равенства состоит из двух знаков «равно». Оператор = (один знак) — это оператор присваивания, о котором будет рассказано позже.

В данном примере все секции являются истиной:

if 1 == 1 then
	-- истина
end

if 10 > 5 then
	-- истина
end

if 5 < 10 then
	-- истина
end

if 10 <= 10 then
	-- истина
end

if 10 >= 9 then
	-- истина
end

if 5 ~= 10 then
	-- истина
end

Логические операторы

В Lua существует несколько логических операторов:

Оператор Значение
and и
or или
not не

Данные операторы позволяют группировать условия для секций. Наглядный пример:

if 10 > 5 and 10 > 7 then
	syschat("банан ") -- мы увидим это сообщение
else
	syschat("мармелад ") -- это сообщение мы не увидим
end

Данный пример можно прочитать так: если 10 больше 5 и 10 больше 7, то показываем в чат слово «банан», иначе показываем в чат слово «мармелад». Здесь условие будет истиной только в том случае, если оба выражения являются истиной. Если в примере выше 10 > 7 поменять на 7 > 10, то в чат отобразится слово «мармелад».

Пример с оператором or:

if 7 > 55 or 10 > 5 then
	syschat("нутелла ") -- мы увидим это сообщение
else
	syschat("варенье ") -- это сообщение мы не увидим
end

Данный пример можно прочитать так: если 7 больше 55 или 10 больше 5, то показываем в чат слово «нутелла», иначе показываем в чат слово «варенье». Для оператора or важно, чтобы выполнялось хотя бы одно из условий. В данном случае у нас одно выполняется — 10 больше 5.

Пример с оператором not:

if not (10 > 5) then
	syschat("гороховый суп ") -- это сообщение мы не увидим
else
	syschat("шаверма ") -- мы увидим это сообщение
end

Данный оператор меняет ложь на истину и наоборот. В данном примере у нас 10 больше 5 — это истина, но оператор поменял истину на ложь, потому что шаверма вкуснее горохового супа, поэтому сработала секция else.

Операторы можно компоновать. Например, вот так:

if not ((10 > 5 and 10 > 6) or (11 > 3 and 43 < 6)) then
	syschat("фалафель ")
else
	syschat("брокколи ")
end

Попробуйте самостоятельно догадаться, какое слово будет выведено в чат. (10 > 5 and 10 > 6) — это истина, а на второе выражение можно даже не смотреть. И истина меняется на ложь оператором not. Это будет «брокколи».

У операторов and и or есть важная особенность. Если у оператора and первое условие является ложью, то второе условие он даже не проверяет. Если у оператора or первое условие является истиной, то второе условие он уже не проверяет. Подробно этот момент будет рассмотрен в углубленном изучении Lua, там же будет объяснено, почему это важно.

Арифметические операторы

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

Оператор Значение
+ сложение
- вычитание
* умножение
/ деление
^ возведение в степень

Использовать их можно, например, так:

if 50 == 10 + 40 then
	syschat("печенье ")
end

Порядок выполнения операторов такой же, как в обычной арифметике. Но если вам необходимо изменить порядок, вы можете также, как и в арифметике, использовать скобки:

if 140 == 10 * 4 + 10 then
	syschat("зефир ") -- это сообщение мы не увидим
end

if 140 == 10 * (4 + 10) then
	syschat("конфеты ") -- мы увидим это сообщение
end

Оператор возведения в степень работает так же, как и обычная степень в арифметике. То бишь код 5 ^ 2 идентичен арифметической записи 52. В арифметической записи данный оператор выполняется в первую очередь, даже раньше умножения и деления.

Переменные

Переменные — это способ временного хранения данных. Переменной присваивается имя и значение:

taco = 50

В данном примере мы переменной taco присвоили значение 50. Оператор = называется «оператор присваивания». Использовать это можно так:

taco = 50

if taco > 10 then
	syschat("арбуз ")
end

Так как переменная taco равна числу 50, то она больше числа 10. Разумеется, переменные можно перезаписывать:

taco = 50

if taco > 10 then
	syschat("арбуз ") -- мы увидим это сообщение
end

taco = 1000

if taco > 420 then
	syschat("вареник ") -- это сообщение мы тоже увидим
end

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

taco = 50 -- правильная переменная
taco_buritto = 50 -- правильная переменная
taco_123 = 50 -- правильная переменная
taco23_45buritto = 50 -- правильная переменная
_taco_123_buritto = 50 -- правильная переменная
Taco_Buritto = 50 -- правильная переменная

123taco = 50 -- неправильная переменная
taco-buritto = 50 -- неправильная переменная
taco_буритто = 50 -- неправильная переменная

Переменные не могут принимать имена зарегистрированных ключевых слов; вот их список: and, break, do, else, elseif, end, false, for, function, if, in, local, nil, not, or, repeat, return, then, true, until, while, quest, state, when, begin и with. Также названия переменных не должны совпадать с названиями семейств функций, самих функций, квестов, стадий, триггеров и таймеров (некоторые из этих терминов будут объяснены в будущем).

Выше был показан пример использования глобальной переменной. Существуют еще локальные переменные, которые задаются с помощью ключевого слова local:

local buritto = 50

Отличие локальной переменной от глобальной в том, что её область видимости ограничена. Наглядный пример:

local buritto = 50

if buritto == 50 then
	syschat("буритто ") -- мы увидим это сообщение

	local taco = 70
end

if taco == 70 then
	syschat("тако ") -- это сообщение мы не увидим
end

Локальные переменные видны только в секции, в которой они были заданы:

local buritto = 50

if buritto == 50 then
	syschat("буритто ") -- мы увидим это сообщение

	local taco = 70

	if taco == 70 then
		syschat("чебурек ") -- мы увидим это сообщение

		if taco == 70 and buritto == 50 then
			syschat("курочка гриль ") -- мы увидим это сообщение
		end
	end
end

if taco == 70 then
	syschat("тако ") -- это сообщение мы не увидим
end

У глобальных переменных такого ограничения нет. Если бы мы убрали ключевое слово local, когда задавали переменную taco, то мы бы увидели и последнее сообщение — «тако». Может показаться, что глобальные переменные удобнее локальных из-за того, что у них нет ограничения по области видимости, но все же лучше использовать глобальные только там, где это необходимо. При их использовании сложнее запутаться. Вред глобальных переменных будет объяснён в более глубогом изучении Lua.

Данный пример идентичен тому, что демонстрировался выше, но мы увидим последнее сообщение без помощи глобальных переменных:

local buritto = 50
local taco

if buritto == 50 then
	syschat("буритто ") -- мы увидим это сообщение

	taco = 70

	if taco == 70 then
		syschat("чебурек ") -- мы увидим это сообщение

		if taco == 70 and buritto == 50 then
			syschat("курочка гриль ") -- мы увидим это сообщение
		end
	end
end

if taco == 70 then
	syschat("тако ") -- мы увидим это сообщение
end

В строке local taco мы объявили переменную taco как локальную, но не задали ей значение. В строке taco = 70 мы задали локальной переменной значение. Сначала Lua проверяет, существует ли локальная переменная с именем taco, и если существует, то перезаписывает ее значение, а если не существует, то перезаписывает значение глобальной переменной.

Комментарии в Lua

Комментарии в коде позволяют вам внести в него некую ясность для людей, которые потом этот код будут просматривать. Комментарии можно задать двумя способами: двумя дефисами -- и вот так: --[[ ... ]].

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

Второй вариант позволяет закомментировать несколько строк. Пример:

--[[
	В переменной milk указывается количество литров молока, необходимое для приготовления каши на троих человек.
	Если будете менять переменную, то обязательно сообщите мне об этом.
]]

milk = 1

Разумеется, всё, что находится в комментариях, является простым текстом и никак не влияет на код:

local pizza = 50

-- pizza = 12

if pizza > 30 then
	syschat("пицца ") -- мы увидим это сообщение
end

Типы данных

В Lua существует несколько типов данных. В примерах выше мы использовали только числа, строки и несознательно булевы выражения, но существует еще несколько:

  • number — числа. Числами в Lua являются как целые числа, так и с плавающей точкой. Например, 343 и 34.4 — это всё числа.
  • string — строки. Строкой считается, например, "мороженое", а также числа, заключенные в кавычки. Подробнее в примере ниже.
  • nil — ничего. Данный тип подразумевает собой пустоту.
  • boolean — булево выражение. Данный тип может быть либо true (истина), либо false (ложь). Данный тип будет рассмотрен чутка позже.
  • table — таблицы. Например, {10, 23}, Данный тип будет рассмотрен позже.

Существует еще два типа данных — userdata и thread, но они при написании квестов не используются, поэтому мы их рассматривать не будем.

Данный пример демонстрирует типы данных. Функция type() сообщает тип данных, которые в нее заключены, а функция syschat() выводит эти данные в чат:

syschat(type(123)) --> number
syschat(type(123.432)) --> number

syschat(type("123")) --> string
syschat(type("мороженка ")) --> string
syschat(type("мороженка за 123 рубля ")) --> string
syschat(type(" ")) --> string
syschat(type("")) --> string

syschat(type(syschat)) --> function
syschat(type(type)) --> function

syschat(type(true)) --> boolean
syschat(type(false)) --> boolean
syschat(type(10 > 5)) --> boolean

syschat(type({213, 123})) --> table
syschat(type({})) --> table

local table_example = {213, 123}
syschat(type(table_example[1])) --> number

-- -- -- -- -- -- -- -- -- --

syschat(type(arwerdvdw3qr)) --> nil

local arwerdvdw3qr

syschat(type(arwerdvdw3qr)) --> nil

arwerdvdw3qr = 123

syschat(type(arwerdvdw3qr)) --> number

Обратите внимание на фрагмент кода, отделенный чертой. Т.к. не существует функции arwerdvdw3qr() и переменная не задана, то тип данных является nil. Но вдруг мы задаем переменную с таким именем, присваиваем ей число и тип данных становится number.

В арифметических выражениях числа, являющиеся строками, автоматически преобразуются в формат number:

if "5" + 5 == 10 then
	syschat("собачий корм ")
end

Важно! В арифметических выражениях могут участвовать только числа. Участие данных другого типа приведет к ошибке.

Булев тип данных представляет собой либо истину (true), либо ложь (false):

local dumpling = 100 > 50

В переменной dumpling содержится истина, то бишь true. Использовать это можно так:

local dumpling = 100 > 50

if dumpling then
	syschat("пельмени ")
end

Более простой вариант использования булевых выражений выглядит так:

local is_virgin = true
local has_girlfriend = false

Обратите внимание на то, что true и false в примере выше — это не переменные, а зарезервированные ключевые слова, которые означают истину и ложь соответственно.

Также некоторые функции могут сообщать истину или ложь. Например, функция pc.is_gm() сообщает, является ли игрок администратором или нет. Если он администратор, то сообщается истина, а иначе — ложь:

if pc.is_gm() then
	syschat("я администратор ")
else
	syschat("я не администратор ")
end

Вот еще несколько секций, условия которых являются истиной:

local a = true

if a then
	-- истина
end

a = false

if not a then
	-- истина
end

if a == false then
	-- истина
end

if not (a == true) then
	-- истина
end

У типа данных nil есть маленькая особенность: в управляющих конструкциях он интерпретируется как ложь, хоть ей и не является:

-- Обратите внимание на то, что переменную rafaello мы нигде не задавали, поэтому она равна nil

if rafaello then
	syschat("рафаэлло ") -- это сообщение мы не увидим
end

if not rafaello then
	syschat("рафаэлло ") -- мы увидим это сообщение
end

if rafaello == nil then
	syschat("рафаэлло ") -- мы увидим это сообщение
end

if rafaello == false then
	syschat("рафаэлло ") -- это сообщение мы не увидим
end

Конкатенация строк

Конкатенация строк — это их объединение. Объединяются строки оператором .. (две точки). Простой пример:

--[[
	В Lua можно одним выражением задавать сразу несколько значений разным переменным.
	Тут я задал переменной 'a' значение "abc", а переменной 'b' - "def"
]]

local a, b = "abc", "def"

if a .. b == "abcdef" then
	syschat("пончик ")
end

Разумеется, объединять можно не только переменные, но и числа со строками:

local food = "Пончик "

syschat(food .. "был очень " .. "вкусным и стоил всего " .. (5 * 5) .. " рублей.")

--[[
	Выведет сообщение в чат:
	Пончик был очень вкусным и стоил всего 25 рублей.
]]

Арифметические выражения всегда заключайте в скобки, если вы производите вычисления прямо внутри строки, как показано примером выше.

Еще несколько примеров:

syschat(12 .. 34) --> 1234

local x = "Hello"
local y = " World"

syschat(x .. y) --> Hello World
syschat(x) --> Hello

local z = 15 * 3

syschat(x .. y .. " " .. z) --> Hello World 45

local n = x .. y

syschat(n) --> Hello World

local a = 5
local b = 10

syschat((a .. b) * 2) --> 1020