Garry's Mod

Garry's Mod

Not enough ratings
Программируем на Lua | GLua для начинающих
By Dr. L
НЕ душное руководство по программированию на GLua.
2
   
Award
Favorite
Favorited
Unfavorite
Введение
Всем привет! Сегодня вы узнаете о новом языке программирования - Lua, и о его модификации для игры Garry's mod, который называется GLua.

Это руководство - серия других моих руководств по программированию.

Зачем знать Lua? Всё просто! На Lua пишут большинство модификаций для игры Garry's mod, и зная данный язык программирования вы сможете создавать свои скрипты и модификации для данной игры!

Данное руководство существует благодаря поддержке активного сообщества Steam.
Также, я хотел поблагодарить всех тех людей, которые оценивали мои прошлые руководства, спасибо, что поддерживаете меня, и мои руководства :)

Введение в Lua
Как я уже говорил,
GLua — это модифицированная версия языка программирования Lua, специально адаптированная для Garry's Mod (GMod). Она позволяет создавать аддоны, скрипты и модификации для игры, расширяя её функционал и добавляя новые возможности.
Среда разработки
Писать код и запускать его мы будем сразу в Garry's mod, для этого нам понадобятся 2 расширения из мастерской стима:
  • EasyChat - Улучшенный чат для garry's mod, как раз в нем работает расширение Lua Code Editor.
  • Lua Code Editor - Интерфейс для написания и запуска кода прямо в Garry's mod.
https://steamoss.com/sharedfiles/filedetails/?id=1182471500
https://steamoss.com/sharedfiles/filedetails/?id=2173212443

После того, как вы подпишитесь на эти аддоны, зайдите в Garry's mod, и зайдите на какую то карту, любую.
Когда вы откроете чат, он, скорее всего, будет не привычный для вас (конечно если вы не пользовались этим расширением раньше)

*Интерфейс чата*

Lua Code Editor как раз добавит вкладку Lua, перейдите в неё.

Чтобы начать писать код, создайте новый файл, во вкладке Lua нажмите на кнопку File слева сверху), и нажмите New.


После этого вы сможете писать код.
Чтобы запустить его нажмите на эту кнопку: (Зелёный треугольник)

Первая программа
Как обычно, мы не будем сразу углубляться в синтаксис и тонкости языка Lua, для начала просто напишем скрипт, который выводит в консоли "Hello world!".

Перепишите, или вставьте этот код:
print("Hello world!")

После этого, запустите его.
Когда вы его запустите, в консоли (которая обычно открывается на ~) вы увидите это сообщение:


Если скрипт запустился, и вы увидели сообщение в консоли, поздравляю, вы написали свой первый скрипт!
Основы Lua
Перед изучение GLua, мы сначала изучим основы Lua.

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

В Lua переменные могут быть глобальными или локальными.
  • Глобальные переменные доступны из любой части кода.
  • Локальные переменные ограничены блоком кода, в котором они объявлены. (к примеру в функциях)
Пример:
-- Глобальная переменная myGlobalVar = 10 -- Локальная переменная local myLocalVar = 5 print(myGlobalVar) -- Вывод в консоль: 10 print(myLocalVar) -- Вывод в консоль: 5

"--" это комментарий, он не на что не влияет, там можно оставлять заметки.

Рекомендация: Используйте локальные переменные (local), чтобы избежать конфликтов и повысить производительность, так как обращение к локальным переменным быстрее, чем к глобальным.

Типы Данных
Lua имеет несколько основных типов данных:
  • nil: Отсутствие значения.
  • boolean: true или false.
  • number: Числа (дробные и целые).
  • string: Строки текста.
  • function: Функции.
  • table: Таблицы (ассоциативные массивы, аналог объектов).
  • userdata: Необычные типы данных, обычно используемые в GLua.
  • thread: Потоки.
Примеры:
local myNil = nil local myBool = true local myNumber = 42 local myString = "Hello, Lua!" local myFunction = function() print("Function") end local myTable = {key = "value", anotherKey = 123}

Операторы
Lua поддерживает различные операторы для выполнения операций над данными.
Арифметические операторы (простая математика):
  • + : Сложение
  • - : Вычитание
  • * : Умножение
  • / : Деление
  • % : Остаток от деления
  • ^ : Возведение в степень

Пример:
local a = 10 local b = 3 print(a + b) -- 13 print(a - b) -- 7 print(a * b) -- 30 print(a / b) -- 3.3333 print(a % b) -- 1 print(a ^ b) -- 1000

P.s. Остаток от деления - это дробная часть, оставшаяся после деления чисел.
К примеру мы делим 10 на 3, и получается 3.333... и .333 и есть остаток от деления.

Логические операторы
Работает над двумя переменными.
and : Логическое "и"
or : Логическое "или"
not : Логическое "не"

Пример:
local x = true local y = false print(x and y) -- false print(x or y) -- true print(not x) -- false

Пояснение:
Логическое И вернёт true, если обе переменные равны true,
Логическое ИЛИ вернёт true, если хотя бы одна из них равна true,
Логическое НЕ вернёт инвертированное значение, то есть, если было true, вернёт false, и false аналогично.

Операторы сравнения
Работает над двумя переменными.
  • == : Равно
  • ~= : Не равно
  • < : Меньше
  • > : Больше
  • <= : Меньше или равно
  • >= : Больше или равно

Пример:
local a = 5 local b = 10 print(a == b) -- false print(a ~= b) -- true print(a < b) -- true print(a > b) -- false print(a <= b) -- true print(a >= b) -- false

Условные Конструкции
Позволяют выполнять код в зависимости от условий.
В Lua есть 3 основные условные конструкции.
if, elseif, else.

Синтаксис:
if условие1 then -- Код выполняется, если условие1 истинно elseif условие2 then -- Код выполняется, если условие2 истинно else -- Код выполняется, если все условия ложны end

P.s. elseif и else не обязательные.

Примеры:
-- только if local x = 100 if x == 100 then print("Meow") end
-- с elseif local x = 100 if x == 50 then print("Sus") elseif x == 100 then print("100x Meow") end
-- с else и elseif local health = 75 if health == 100 then print("Здоровье в норме") elseif health ~= 100 and health > 50 then print("Надо полечиться") else print("Проблемы со здоровьем") end

Циклы
Позволяют повторять блок кода несколько раз.

Цикл for
Синтаксис:
for инициализация, условие, шаг do -- Код end

Пример:
for i = 1, 5 do print("Итерация " .. i) end

Вывод:
Итерация 1 Итерация 2 Итерация 3 Итерация 4 Итерация 5

Цикл while

Синтаксис:
while условие do -- Код end

Пример:
local count = 1 while count <= 5 do print("Счетчик: " .. count) count = count + 1 end

Вывод:
Счетчик: 1 Счетчик: 2 Счетчик: 3 Счетчик: 4 Счетчик: 5

Функции
Функции позволяют группировать код для повторного использования.

Объявление и вызов функций

Синтаксис:
local function имяФункции(параметры) -- Код функции end

-- Вызов функции
имяФункции(аргументы)

Пример:
local function greet(name) print("Привет, " .. name .. "!") end greet("Dr. L") -- Вывод: Привет, Игрок!

Функции с возвращаемыми значениями

Пример:
local function add(a, b) return a + b end local результат = add(5, 7) print(результат) -- Вывод: 12

Таблицы
Таблицы в Lua — это основной структурный тип данных, который может использоваться как массивы, словари (ассоциативные массивы) и даже объекты.

Создание таблицы
Пример:
-- Таблица как массив local fruits = {"яблоко", "банан", "апельсин"} -- Таблица как словарь local player = { name = "Игрок", health = 100, armor = 50 }

Доступ к элементам таблицы
Пример:
print(fruits[1]) -- Вывод: яблоко print(player["health"]) -- Вывод: 100

Добавление и изменение элементов
Пример:
-- Добавление элемента table.insert(fruits, "груша") -- Изменение значения player.health = 90

Перебор таблицы
Пример:
-- Перебор массива for index, fruit in ipairs(fruits) do print(index, fruit) end -- Перебор словаря for key, value in pairs(player) do print(key, value) end

Вывод:
1 яблоко 2 банан 3 апельсин 4 груша name Игрок health 90 armor 50
Минутка отдыха
Предыдущая глава была О-О-О-ОЧЕНЬ большая, но это всего пол пути нашего изучения GLua.
Мы изучили основы и синтаксис Lua, но нам так же нужно изучить основы GLua.

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

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

Так что можете просто посмотреть на эту гифку и попить чай :)


Основы GLua
Теперь мы будем изучать GLua!
Надеюсь вы отдохнули, и готовы к изучению основных концепций GLua.

GLua расширяет стандартные возможности Lua, предоставляя функции и объекты, специфичные для Garry's Mod. Здесь мы рассмотрим ключевые концепции.

Все под-главы этой главы будут разделены в обычные главы, чтобы не нагружать одну главу.
Хуки (Hooks)
Хуки позволяют подключать свои функции к определённым событиям в игре. Это мощный инструмент для расширения функционала.

На данной функции делается большинство пользовательских интерфейсов, да и в целом модификаций.

Основные хуки
  • Think: Вызывается каждый кадр.
  • HUDPaint: Используется для отрисовки на экране.
  • PlayerInitialSpawn: Срабатывает, когда игрок впервые присоединяется к серверу.
  • EntityTakeDamage: Срабатывает, когда сущность получает урон.

Использование хуков
Синтаксис:
hook.Add("ИмяХука", "УникальныйИдентификатор", function(аргументы) -- Код end)

Пример:
hook.Add("PlayerInitialSpawn", "WelcomeMessage", function(ply) ply:PrintMessage(HUD_PRINTTALK, "Добро пожаловать на сервер, " .. ply:Nick() .. "!") end)

Объяснение:
  • hook.Add: Функция для добавления хука.
  • "PlayerInitialSpawn": Имя хука, к которому подключаемся.
  • "WelcomeMessage": Уникальный идентификатор хука. Используется для последующего удаления хука, если необходимо.
  • function(ply): Функция, которая будет вызвана при срабатывании хука. В данном случае принимает игрока ply как аргумент.
Удаление хуков

Синтаксис:
hook.Remove("ИмяХука", "УникальныйИдентификатор")

Пример:
hook.Remove("PlayerInitialSpawn", "WelcomeMessage")

Подробнее про хуки:
-- Think (выполняется каждый кадр) hook.Add("Think", "MyThinkHook", function() -- Код здесь выполняется каждый кадр end) -- Initialize (выполняется при загрузке скрипта) hook.Add("Initialize", "MyInitHook", function() print("Скрипт загружен!") end) -- PlayerInitialSpawn (когда игрок впервые присоединяется) hook.Add("PlayerInitialSpawn", "MySpawnHook", function(ply) print(ply:Nick() .. " присоединился к серверу!") end) -- Использование клавиш hook.Add("PlayerButtonDown", "MyButtonHook", function(ply, button) if button == KEY_F then print(ply:Nick() .. " нажал F") end end) -- Получение урона hook.Add("EntityTakeDamage", "MyDamageHook", function(target, dmginfo) if target:IsPlayer() then print(target:Nick() .. " получил " .. dmginfo:GetDamage() .. " урона") end end) -- Использование чата hook.Add("PlayerSay", "MyChatHook", function(ply, text, team) if string.lower(text) == "!help" then ply:ChatPrint("Это помощь!") return "" -- Предотвращает отображение команды в чате end end) -- Отрисовка после основных объектов hook.Add("PostDrawOpaqueRenderables", "My3DRenderHook", function() cam.Start3D() for _, ply in ipairs(player.GetAll()) do local pos = ply:GetPos() render.DrawWireframeSphere(pos, 32, 16, 16, Color(255, 0, 0)) end cam.End3D() end) -- Отрисовка эффектов hook.Add("RenderScreenspaceEffects", "MyEffectHook", function() local tab = { ["$pp_colour_addr"] = 0, ["$pp_colour_addg"] = 0, ["$pp_colour_addb"] = 0, ["$pp_colour_brightness"] = 0, ["$pp_colour_contrast"] = 1, ["$pp_colour_colour"] = 0.5, ["$pp_colour_mulr"] = 0, ["$pp_colour_mulg"] = 0, ["$pp_colour_mulb"] = 0 } DrawColorModify(tab) end)
Работа с Сущностями (Entities)
Сущности — это объекты в мире игры, такие как игроки, NPC, пропсы и т.д.

Создание сущности
Пример: Создание пропа
local function CreateProp() local prop = ents.Create("prop_physics") if not IsValid(prop) then return end prop:SetModel("models/props_c17/oildrum001.mdl") prop:SetPos(Vector(0, 0, 100)) prop:Spawn() end hook.Add("PlayerInitialSpawn", "SpawnPropOnJoin", function(ply) CreateProp() end)

Объяснение:
  • ents.Create: Создаёт новую сущность указанного класса.
  • IsValid: Проверяет, была ли сущность успешно создана.
  • SetModel: Устанавливает модель сущности.
  • SetPos: Устанавливает позицию сущности в мире.
  • Spawn: Спавнит сущность в мире.

Поиск сущностей
Примеры:
Поиск по классу:
local props = ents.FindByClass("prop_physics") for _, prop in ipairs(props) do print(prop:GetModel()) end

Поиск в радиусе:
local entities = ents.FindInSphere(Vector(0, 0, 0), 500) for _, ent in ipairs(entities) do print(ent:GetClass()) end
Консольные команды
С помощью данной функции вы сможете создавать свои консольные команды!

Синтаксис
-- Простая команда concommand.Add("mycommand", function(ply, cmd, args) print("Команда выполнена!") end) -- Команда с аргументами concommand.Add("say_hello", function(ply, cmd, args) local name = args[1] or "noname" -- если имя не указано, то заменяет его на noname print("Привет, " .. name .. "!") end)

После того, как вы запустите этот код, в консоли появятся созданные вами команды!
Основные функции отрисовки
Текст
-- Простой текст draw.SimpleText( "Текст", -- текст "DermaDefault", -- шрифт 100, -- x позиция 100, -- y позиция Color(255,255,255),-- цвет TEXT_ALIGN_LEFT, -- горизонтальное выравнивание TEXT_ALIGN_TOP -- вертикальное выравнивание ) -- Текст с тенью draw.SimpleTextOutlined( "Текст с тенью", -- текст "DermaDefault", -- шрифт 100, -- x позиция 100, -- y позиция Color(255,255,255),-- цвет текста TEXT_ALIGN_LEFT, -- гориз. выравнивание TEXT_ALIGN_TOP, -- верт. выравнивание 1, -- толщина обводки Color(0,0,0) -- цвет обводки )

Примитивы
-- Прямоугольник surface.SetDrawColor(255, 0, 0) -- красный цвет surface.DrawRect(x, y, width, height) -- Линия surface.DrawLine(x1, y1, x2, y2) -- Полигон surface.DrawPoly({ {x = 100, y = 100}, {x = 200, y = 100}, {x = 150, y = 200} })

Изображения и текстуры
-- Загрузка материала local myMaterial = Material("path/to/material.png") -- Отрисовка материала surface.SetMaterial(myMaterial) surface.SetDrawColor(255, 255, 255) surface.DrawTexturedRect(x, y, width, height) -- Отрисовка повернутого материала surface.DrawTexturedRectRotated(x, y, width, height, angle)

Интерактивные элементы
local function IsMouseOver(x, y, w, h) local mouseX, mouseY = gui.MousePos() return mouseX >= x and mouseX <= x + w and mouseY >= y and mouseY <= y + h end hook.Add("HUDPaint", "DrawInteractiveButton", function() local x, y = 100, 100 local w, h = 200, 50 -- Проверка наведения мыши local isHovered = IsMouseOver(x, y, w, h) -- Изменение цвета при наведении surface.SetDrawColor(isHovered and Color(100, 100, 255) or Color(50, 50, 255)) surface.DrawRect(x, y, w, h) -- Текст кнопки draw.SimpleText( "Нажми меня!", "DermaDefault", x + w/2, y + h/2, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) end) -- Обработка клика hook.Add("GUIMousePressed", "HandleButtonClick", function(mouseCode) if mouseCode == MOUSE_LEFT then local x, y = 100, 100 local w, h = 200, 50 if IsMouseOver(x, y, w, h) then print("Кнопка нажата!") end end end
HUD (Heads-Up Display)
HUD - это наш интерфейс, в котором отображается здоровье, броня и тд.
Его можно изменить, или полностью переделать!

Все это делается через хуки, а конкретнее, через хук HUDPaint.

Несколько примеров
Базовый HUD
-- Простой HUD с здоровьем hook.Add("HUDPaint", "MySimpleHUD", function() local ply = LocalPlayer() if not IsValid(ply) then return end -- Параметры local health = ply:Health() local armor = ply:Armor() local screenW = ScrW() local screenH = ScrH() -- Отрисовка здоровья draw.SimpleText( "HP: " .. health, "DermaLarge", screenW * 0.1, screenH * 0.9, Color(255, 0, 0), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER ) -- Отрисовка брони draw.SimpleText( "AP: " .. armor, "DermaLarge", screenW * 0.1, screenH * 0.95, Color(0, 0, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER ) end)

Давайте разберём его по частям!
  • hook.Add("HUDPaint", "MySimpleHUD", function() - хук отрисовки дисплея.
  • local ply = LocalPlayer() - объект нашего персонажа.
  • if not IsValid(ply) then return end - просто проверка, чтобы не было ошибок.
  • draw.SimpleText(...) отрисовывает текст.
Советы:
  • Практикуйтесь регулярно: Чем больше вы пишете код, тем лучше понимаете язык.
  • Читайте документацию: Официальная документация — лучший источник информации.
  • Изучайте чужой код: Это поможет вам узнать новые методы и подходы.
  • Участвуйте в сообществах: Общение с другими разработчиками ускорит ваш прогресс.
  • Не бойтесь ошибок: Ошибки — это часть процесса обучения. Используйте их для улучшения своих навыков.

Конец
Данное руководство было ооооочень длинным, но надеюсь, вам оно понравилось :)
Это руководство ещё будет изменяться, дополняться, и так далее.

Возможно, данное руководство немного сырое, так что надеюсь, вы сможете в комментариях указать на них.
Спасибо, что прочитали это руководство, вы также можете поддержать меня, поставив хорошую оценку данному руководству, а также, вы можете наградить его :3

Удачи в изучении языков программирования, и в написании скриптов!



Другие руководства:
https://steamoss.com/sharedfiles/filedetails/?id=3401446439
https://steamoss.com/sharedfiles/filedetails/?id=3395692013
https://steamoss.com/sharedfiles/filedetails/?id=3390154519
https://steamoss.com/sharedfiles/filedetails/?id=3397931731
https://steamoss.com/sharedfiles/filedetails/?id=3389441554
12 Comments
outerty 6 Jan @ 4:23am 
Теперь ждём руководство как перенести моды из Gmod в халву 2:spycon:
Kumbka_boB 5 Jan @ 11:26am 
да обязательно, руководства твои полезны, одно из твоих руководств стояло на первом месте так и не дав мне сдвинутся со второго, а значит полезные руководства замечают чаще чем всякую рофельную ерунду :gordon:
Dr. L  [author] 5 Jan @ 11:20am 
Обращайтесь :)
Если данное руководство поддержет сообщство, и в целом эту идею, я могу выпустить подробное руководство о созданиие гайдов в стиме!
Kumbka_boB 5 Jan @ 11:07am 
работает спасибо:gordon:
Kumbka_boB 5 Jan @ 9:29am 
спасибо большое, потом опробую :gordon:
Dr. L  [author] 5 Jan @ 6:58am 
Dr. L  [author] 5 Jan @ 6:57am 
чтобы добавить гифку по ссылке, ты можешь сделать вот так:
[screenshot=1;sizeOriginal,inline;здесь ссылка][/screenshot]
Kumbka_boB 5 Jan @ 3:45am 
чувааак имба туторы, не подскажешь как гифки добавлять в руководство? я в инете инфы не нашел :gordon:
Tofca 5 Jan @ 2:50am 
سيتم إعدامي غدا😂
Luntik 5 Jan @ 1:22am 
Прекрасное руководство. |・ω・)
Наткнулся на него совершенно случайно и до этого вообще не интересовался программированием. Но вот, прочитав руководство, понял, что мне это интересно. Всё руководство прочёл на одном дыхании, уж очень оно хорошо написано, самое главное, что интересно. Иногда возникали небольшие проблемы с пониманием, но я в принципе первый раз что-то подобное читал и делал. Теперь вот думаю углубиться в программирование. В общем, спасибо тебе за это прекрасное руководство :)