Как сделать аддон для Garry’s Mod и загрузить его в Мастерскую

Аддон для Garry’s Mod — это обычная папка с файлами Lua, моделями и материалами, которая опубликована как отдельный предмет в Мастерской Steam. Чтобы её туда отправить, нужны три вещи: правильная структура папок, файл описания addon.json и упаковка через официальные утилиты gmad и gmpublish. Дальше — по шагам: от пустой папки до опубликованного аддона с иконкой.

Что понадобится

  • Установленный Garry’s Mod и аккаунт Steam, привязанный к игре (публикация в Мастерскую идёт от вашего аккаунта).
  • Любой текстовый редактор с подсветкой Lua — подойдёт VS Code, Notepad++ или даже обычный «Блокнот». Специальной IDE Facepunch не требует.
  • Если планируете свою модель или текстуру — отдельный инструмент (Blender, Crowbar для компиляции .mdl) и время на изучение; в этом гайде эта часть только упоминается, для первого аддона проще обойтись стандартными моделями игры или чужими ресурсами по лицензии, которая явно разрешает переработку.
  • 512×512 JPEG-картинка для иконки Мастерской — понадобится на последнем шаге.

Если вы ещё не разбирались, как вообще устанавливаются готовые аддоны, лучше сначала посмотреть тот материал: структура папки, которую вы скачиваете из Мастерской, — это ровно то, что вы соберёте своими руками в этом гайде.

Структура аддона

Аддон — это папка, а не единый файл. Внутри неё Garry’s Mod ищет подпапки по строго фиксированным именам; всё остальное игра просто игнорирует. Не все папки обязательны — создавайте только то, что реально используете.

ПапкаЧто туда кладут
lua/autorun/Скрипты, которые выполняются автоматически и на сервере, и на клиенте при загрузке Lua.
lua/autorun/client/То же самое, но выполняется только на клиенте.
lua/autorun/server/Выполняется только на сервере.
lua/weapons/Скрипты, которые Garry’s Mod загружает как SWEP — скриптовое оружие.
lua/entities/Скрипты сущностей (SENT) — от простых точек привязки до NPC.
materials/Текстуры и .vmt-материалы.
models/Скомпилированные модели .mdl и всё, что к ним прилагается.
sound/Звуковые файлы (папка называется в единственном числе).

Рядом с этими папками, в корне аддона, лежит файл addon.json — без него Мастерская не примет .gma. Он описывает сам аддон, а не игровой контент:

{
    "title": "Название вашего аддона",
    "type": "weapon",
    "tags": ["fun", "realism"],
    "ignore": [
        "*.psd",
        "*.vcproj",
        "*.bak"
    ]
}

title — имя, которое увидят игроки. type — один из фиксированных типов: gamemode, map, weapon, vehicle, npc, tool, effects, model, entity или servercontent — выбирайте ближайший по смыслу к тому, что делает аддон. tags — не больше двух меток из ограниченного набора Мастерской (например, fun, roleplay, realism, scenic, cartoon, build). ignore — маски файлов, которые не нужно паковать в .gma (черновики, файлы редактора, бэкапы).

Если аддон рассчитан на установку на сервер, а не только локально, пути и способ раздачи через Мастерскую стоит продумать вместе с тем, как вы вообще поднимаете сервер Garry’s Mod — на сервере такие вещи, как resource.AddWorkshop, отвечают за то, чтобы аддон скачался у всех подключившихся игроков.

Первый Lua-скрипт

Прежде чем писать оружие или сущность, стоит убедиться, что Lua вообще подхватывает ваши файлы. Создайте файл lua/autorun/myaddon_hello.lua с простым хуком:

hook.Add("Initialize", "MyAddon_Hello", function()
    print("MyAddon: Lua загрузился, всё на месте")
end)

hook.Add("PlayerSay", "MyAddon_Echo", function(ply, text)
    print(ply:GetName() .. " написал: " .. text)
end)

hook.Add(событие, идентификатор, функция) — базовый способ подписаться на игровое событие, не переопределяя код игры напрямую. Initialize сработает один раз при запуске Lua, PlayerSay — при каждом сообщении в чат. Идентификатор нужен, чтобы потом можно было снять хук через hook.Remove или заменить его, не плодя дубликаты.

Результат print() вы увидите в консоли разработчика (клавиша ~) или в консоли сервера, если это серверный код (хук PlayerSay срабатывает только на сервере). Подробнее про запуск и отладку скриптов из консоли — в отдельном материале про консольные команды Garry’s Mod: там же про lua_run и построчный запуск кода без создания файла.

Если после перезапуска карты сообщения в консоли нет, чаще всего скрипт лежит не в той папке или в нём синтаксическая ошибка — её текст (красным или жёлтым) тоже будет в консоли.

Простое оружие (SWEP)

Скриптовое оружие описывается одной Lua-таблицей SWEP. Для первого раза удобнее собрать всё в одном файле lua/weapons/weapon_myaddon_pistol.lua — Garry’s Mod поймёт его как shared-файл и разошлёт клиентам сам, если в начале стоит AddCSLuaFile().

AddCSLuaFile()

SWEP.PrintName = "Мой пистолет"
SWEP.Author = "Вы"
SWEP.Category = "Мои аддоны"
SWEP.Spawnable = true
SWEP.AdminOnly = false

SWEP.ViewModel = "models/weapons/v_pistol.mdl"
SWEP.WorldModel = "models/weapons/w_pistol.mdl"
SWEP.Slot = 1

SWEP.Primary.ClipSize = 12
SWEP.Primary.DefaultClip = 12
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "Pistol"
SWEP.Primary.Delay = 0.3
SWEP.Primary.Sound = Sound("Weapon_Pistol.Single")

function SWEP:PrimaryAttack()
    if not self:CanPrimaryAttack() then return end
    self:ShootBullet(5, 1, 0.05)
    self:TakePrimaryAmmo(1)
    self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
end

SWEP.Category — это заголовок раздела в спавн-меню, SWEP.Spawnable = true делает оружие видимым там же. ViewModel/WorldModel в примере — стандартные модели пистолета из игры, поэтому пример рабочий без единой своей модели. ShootBullet(урон, число_пуль, разброс) — встроенный в базовое оружие метод, который стреляет трассируемыми пулями без ручной работы с трассировкой лучей.

Вместо оружия можно сделать простую сущность (SENT) — например, декоративный физический объект или основу для будущей механики. Самый простой вариант — один файл lua/entities/myaddon_prop.lua (имя файла станет классом сущности):

AddCSLuaFile()

ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Моя сущность"
ENT.Category = "Мои аддоны"
ENT.Spawnable = true

function ENT:Initialize()
    if SERVER then
        self:SetModel("models/props_junk/watermelon01.mdl")
        self:PhysicsInit(SOLID_VPHYSICS)
        self:SetMoveType(MOVETYPE_VPHYSICS)
        self:SetSolid(SOLID_VPHYSICS)
        local phys = self:GetPhysicsObject()
        if IsValid(phys) then phys:Wake() end
    end
end

Сущность появится во вкладке Entities меню спавна в категории «Мои аддоны». Для больших сущностей код обычно разносят на три файла в папке с именем класса: shared.lua, init.lua (сервер) и cl_init.lua (клиент) — так устроено большинство аддонов.

Если в планах — полноценный NPC с поведением, а не просто статичный объект, не пишите логику передвижения с нуля: удобнее взять готовую NPC-базу и разобраться на её примере, как устроены хуки поведения — например, на VJ Base, одной из самых распространённых баз для NPC в Мастерской.

Чтобы проверить изменения без пересборки .gma, редактируйте файлы прямо в папке аддона в garrysmod/addons: многие Lua-файлы игра перезагружает автоматически при сохранении (auto-refresh), а если нет — перезапустите карту. Для одиночных серверных скриптов без входа в игру можно временно подгрузить файл командой lua_openscript (на клиенте — lua_openscript_cl, если сервер разрешает клиентский Lua через sv_allowcslua) — но это разовый запуск кода, а не «горячая перезагрузка»: скрипт выполнится ещё раз поверх уже загруженного.

Если работа с классическим Lua-кодом кажется избыточной для простой логики — переключателей, таймеров, простых условий, — присмотритесь к визуальному программированию через Wiremod и Expression 2: часть задач, для которых новички сразу открывают редактор кода, решается там без единой строчки Lua.

Упаковка и публикация

Когда папка аддона готова, её нужно превратить в один файл .gma и отправить в Мастерскую. Обе утилиты лежат в игре, отдельно скачивать их не нужно: ...\Steam\steamapps\common\GarrysMod\bin\gmad.exe и gmpublish.exe там же.

Шаг 1 — упаковка в .gma. Из командной строки в папке bin:

gmad.exe create -folder "C:\путь\к\папке\аддона" -out "C:\путь\куда\addon.gma"

Шаг 2 — подготовка иконки. Мастерская требует картинку ровно 512×512 пикселей, baseline JPEG (не PNG и не progressive JPEG). Имя файла произвольное, но проще держать его рядом с .gma под тем же именем.

Шаг 3 — первая публикация.

gmpublish.exe create -addon "C:\путь\куда\addon.gma" -icon "C:\путь\куда\addon.jpg"

После успешной загрузки утилита выведет ссылку на страницу аддона в Мастерской и его ID — сохраните этот ID, он понадобится для всех дальнейших обновлений.

Шаг 4 — обновления. Пересобираете .gma тем же gmad.exe create и заливаете новую версию по ID, не создавая новый предмет:

gmpublish.exe update -id "ВАШ_ID" -addon "C:\путь\куда\addon.gma" -changes "Fixed pistol sound"

Текст в -changes попадает в историю изменений на странице аддона; подробное описание изменений можно дописать и прямо на странице предмета в Steam. Иконку тем же способом обновляют командой gmpublish.exe update -id "ВАШ_ID" -icon "новая_иконка.jpg".

Тип и теги, указанные в addon.json, попадают в фильтры Мастерской — если аддон плохо находится в поиске, в первую очередь проверьте, что type и tags действительно описывают содержимое, а не поставлены наугад. Отдельно на размер файла жёстких цифр Facepunch не публикует, но чем тяжелее текстуры и модели, тем менее охотно игроки подписываются и тем дольше грузится карта — оптимизация текстур и удаление неиспользуемых файлов (через ignore в addon.json) стоят потраченного времени.

Правила Мастерской и авторское право

  • Нельзя выкладывать модели, звуки и текстуры из платных игр без разрешения правообладателя — так называемые рипы. Контент, который уже входит в Garry’s Mod (включая встроенный с июля 2025 года контент CS:S и эпизодов HL2), используйте по путям к файлам игры, а не копируйте его внутрь своего аддона.
  • Нельзя публиковать чужой аддон под своим именем или без указания оригинального автора, даже если вы внесли небольшие правки.
  • Steam Workshop имеет собственное лицензионное соглашение — публикуя предмет, вы соглашаетесь с ним; перед первой публикацией стоит прочитать его текст на странице Мастерской, а не только этот гайд.
  • Если используете чужие ресурсы по разрешённой лицензии (например, Creative Commons), указывайте автора и источник в описании аддона — это не формальность, а условие большинства таких лицензий.

Частые ошибки

ПроблемаПричина и что делать
Аддон не появляется в спавн-менюНе указан Spawnable = true у SWEP/ENT, либо файл лежит не в lua/weapons/lua/entities, а в произвольной папке.
Оружие видно только у вас, не у других игроковЗабыт AddCSLuaFile() в начале общего файла — клиенты не получили Lua-код и не могут отрисовать модель.
gmpublish.exe create ничего не публикуетНеверный путь к .gma/иконке в кавычках, иконка не 512×512 или не baseline JPEG, либо не выполнен вход в Steam (утилита использует активную сессию Steam).
Аддон конфликтует с другим по именам файловИмена Lua-файлов и путь модели должны быть уникальны — добавьте в начало имён файлов и путь моделей короткий префикс своего аддона.

Итог / чек-лист

  • Папка аддона собрана по стандартной структуре (lua/autorun, lua/weapons, lua/entities, materials, models, sound) — лишних папок нет.
  • В корне лежит addon.json с корректными title, type и не больше чем двумя tags.
  • Первый Lua-скрипт проверен через print() в консоли — файлы точно загружаются.
  • В SWEP/ENT указаны Spawnable, PrintName, Category; в клиентских/shared-файлах оружия есть AddCSLuaFile().
  • Готова иконка 512×512 baseline JPEG.
  • Аддон упакован через gmad.exe create и опубликован через gmpublish.exe create; ID предмета сохранён для будущих gmpublish.exe update.
  • В аддоне нет чужого контента без разрешения — иначе Мастерская снимет предмет по жалобе правообладателя.

Частые вопросы

Нужно ли платить за публикацию аддона в Мастерской Garry’s Mod?

Нет, размещение своих аддонов в Steam Workshop для Garry’s Mod бесплатно. Требуется только сама игра в вашей библиотеке Steam и выполненный вход в клиент Steam — gmpublish.exe публикует от имени вашего аккаунта.

Можно ли сделать аддон без программирования на Lua?

Да, если аддон — это только модель, карта или набор материалов: тогда Lua вообще не нужен, файл addon.json и правильные папки решают всё. Для логики (оружие, сущности, поведение) без Lua не обойтись, но простые интерактивные механики без кода можно собрать через инструменты вроде Wiremod и Expression 2.

Почему аддон работает у меня, но не у игроков на сервере?

Чаще всего забыт AddCSLuaFile() для клиентских или общих файлов — без него сервер не отправляет Lua-код клиентам. Также стоит проверить, что сервер вообще раздаёт этот Workshop-предмет игрокам при подключении.

Как назвать файл SWEP, чтобы игра его подхватила?

Имя файла в lua/weapons/ становится классом оружия — например, weapon_myaddon_pistol.lua даст оружию класс weapon_myaddon_pistol. Используйте только латиницу, цифры и подчёркивания, без пробелов.

Обязательно ли делать иконку именно 512×512?

Да, это требование Мастерской для gmpublish: точный размер 512×512, формат baseline JPEG. Иконка другого размера или в PNG будет отклонена при публикации.

Как обновить уже опубликованный аддон, не создавая новую страницу в Мастерской?

Пересоберите папку в новый .gma тем же gmad.exe create и вызовите gmpublish.exe update с параметром -id, указав ID существующего предмета. Новая страница при этом не создаётся, обновляется текущая.

Можно ли использовать модели и звуки из Counter-Strike: Source или других игр Valve в своём аддоне?

Использовать можно то, что уже есть в самой Garry’s Mod (с июля 2025 года туда входит и бо́льшая часть контента CS:S и эпизодов HL2), — ссылаясь на эти модели и звуки путями, без копирования файлов в аддон. Перепаковывать ресурсы из других игр без разрешения правообладателя нельзя.

Что делать, если хочется NPC с собственным поведением, а не просто статичную модель?

Не переписывайте систему поведения с нуля — возьмите готовую и хорошо документированную базу для NPC (например, VJ Base) и добавляйте к ней свою модель и настройки поверх уже рабочей логики движения и атаки.