Source Modding — Часть 1 — Основы основ

В мире существует множество игровых движков, но нет ни одного движка, похожего на Source своей историей и особенностями.

В этом (пилотном) уроке мы разберем простейшие действия с исходными кодами SDK, а также внесем наше первое изменение в код Half-Life 2.

35p6ilwrz5fccxsgnk7vtjewpww.png


Вступление


Немножко терминов

Сам по себе Source SDK — набор утилит и программ, помогающих в разработке собственных уровней и модификаций для игры, а также исходные коды Half-Life 2 и эпизодов.

Игра/Мод (Для сурса нет никакой разницы, игра это или мод : p) — скомпилированные исходные коды SDK.


Так почему же именно Source?!


  1. Модульность. Это может показаться минусом для некоторых, но почти все подсистемы движка вынесены в отдельные модули, каждый из которых может быть заменен без пересборки всего движка.
  2. Чрезвычайная гибкость. При достаточном количестве усилий вы можете сделать на Source игру абсолютно любого жанра.
  3. Движок и SDK разрабатывались огромным количеством людей, поэтому код SDK (а также утекший в сеть три раза код движка разных версий, но об этом позже (͡° ͜ʖ ͡°)) состоит из множества разных стилей программирования! Я почти уверен, что именно работа с Source SDK подарила мне умение (но не желание…) читать чужой код.
  4. Порог вхождения. Он не слишком низок и не слишком высок. Достаточно знать C++ и уметь вчитываться в документацию!
  5. К моменту появления идеи о написании туториала у автора попросту не было новой версии юнити.


Что нам необходимо?


  1. Ну прежде всего хотя бы базовые знания C++ (Достаточно знать его на уровне Си с классами).
  2. Любая Microsoft Visual Studio с Multibyte MFC Library и Microsoft Build Tools 2013 (v120/v120_xp). Чтобы не морочить себе голову, можно просто установить VS2013.
  3. Git for Windows или любой другой.
  4. Steam с установленным Source SDK Base 2013 [Single|Multi]player (также необходимо в свойствах «игры» установить бета-версию upstream, иначе мод будет падать)
  5. В будущем также знание HLSL, но не сейчас :)


Введение в сурс дела


Репозиторий

Исходный код SDK находится в репозитории на GitHub. Склонируйте его в любое удобное для вас место:

git clone https://github.com/ValveSoftware/source-sdk-2013.git


Выбор ветки

Если вы хотите написать свой первый мод для Half-Life 2/Episode ½, то используйте директорию sp/ и Source SDK Base 2013 Singleplayer.

Если же вы извращенец и хотите написать свой первый мод для Half-Life 2: Deathmatch, то используйте директорию mp/ и Source SDK Base 2013 Multiplayer.

ВАЖНО: Туториал будет рассматривать программирование под ветку SP, поэтому пути, содержащие hl2 в пересчете на MP могут содержать hl2mp вместо hl2!!!


Стиль кода

Клиентские (client.dll) классы именуются с префиксом C_, а серверные (server.dll) — с префиксом C:

// client.dll
class C_BaseWeapon { ... };
// server.dll
class CBaseWeapon { ... };

Поля класса именуются с префиксом m_, использование венгерской нотации рекомендуется (на то есть свои причины, которые здесь обсуждать нет смысла):

class C_SomeClientClass {
private:
    float m_flTime = 0.0;
};
extern float g_flSomeFloat;
static float s_flSomeStaticFloat;
void SomeFunction(float flValue);


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

SDK, также как и движок, разделён на несколько частей. Вот список проектов, сгенерированных при помощи creategameprojects:


  • client.dll
    Клиентская часть игры.
    Отвечает за рендеринг, предсказания и ввод.
    Расположена: src/game/client/
  • server.dll
    Серверная часть игры.
    Отвечает за игровую логику, ИИ и т.д.
    Расположена: src/game/server/
  • tier1.lib
    Библиотека, содержащая в себе множество полезных фич, например UTL («валвовская» версия STL), interface convention и т.д.
    Расположена: src/tier1/
  • raytrace.lib
    Библиотека, внезапно содержащая в себе функции и типы, предназначенные для рейтрейсинга. Честно говоря, я так и не понял, что библиотека для компиляторов делает здесь.
    Используется компилятором vrad и, судя по утечкам исходных кодов, редактором уровней Valve Hammer Editor.
    Расположена: src/raytrace/
  • mathlib.lib
    Библиотека, содержащая в себе множество типов и функций, используемых в «повседневной» математике Source.
    Расположена: src/mathlib/
  • vgui_controls.lib
    Библиотека, содержащая в себе реализации разных элементов (кнопки, панели) VGUI2.
    Используется почти повсеместно.
    Расположена: src/vgui2/vgui_controls/


VPC

Source SDK имеет свой генератор проектов (sln, Makefile, etc.) с блэкджеком и… кхм…
Называется он Valve Project Creator и находится в src/devtools/bin.

Проекты генерируются автоматически с использованием специальных .VPC файлов. Синтаксис этих файлов прост до безобразия — простой набор пар ключ-значение.

Вот пути до некоторых таких файлов:

src/game/client/client_episodic.vpc
src/tier1/tier1.vpc
src/utils/vrad/vrad_dll.vpc

ВАЖНО: При внесении ЛЮБЫХ изменений в VPC файл решение должно быть заново перегенерировано!


Генерация проектов

Проекты генерируются вызовом скрипта, расположенного в директории src/.
В самом простом случае — достаточно просто открыть src/creategameprojects.bat.
После генерации в src/ будет находиться games.sln.

w5fty2oh0izj78rzegorumuzhou.png


Исключение HL2

SDK имеет внутри себя также разделение на HL2 и Episodic. Использование второго позволит нам иметь некоторые фичи, например отдельную от стамины шкалу заряда фонарика.

И поэтому, чтобы не компилировать лишний код, мы можем просто исключить HL2 из скриптов:


  1. Откройте src/creategameprojects.bat в любом текстовом редакторе.
  2. Удалите из командной строки часть /hl2
  3. Сохраните файл и сгенерируйте проект.


Другие скрипты

Рядом с creategameprojects.bat также лежит его клон для bash, а также два интересных файла — createallprojects.bat и его клон для bash.

Эти два скрипта заставляют VPC создавать проекты не только для чистых библиотек мода, но и для различных утилит, таких как vrad (Radiosity!) или height2normal.

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


Первичная сборка и запуск


Сборка

Чтобы удостовериться, что вы всё сделали правильно, необходимо собрать всё сгенерированное решение. Итак, собираем (вы же ведь открыли решение в IDE?):


  1. Переключите конфигурацию в Release.
    ВАЖНО: При сборке в Debug мод крайне нестабилен!!!
  2. Соберите ВСЁ решение (F6)
  3. Если сборка закончилась с ошибками, повторите шаг 2.
  4. Если ошибки повторяются, пересоздайте проекты (creategameprojects) и повторите все шаги начиная с 1.

После сборки в папке game/mod_hl2/bin/ или game/mod_episodic/bin/ должны появится наши клиентская и серверная библиотеки!


Запуск — Способ 1 — Steam


  1. Копируем нашу папку mod_xxx в путь/до/Steam/steamapps/sourcemods/
  2. Перезапускаем Steam (либо запускаем, если еще этого не сделали…)
  3. Ищем в библиотеке «My First Episodic Mod» или «My First HL2 Mod»
  4. В свойствах устанавливаем дополнительные параметры командной строки:
    -dev -console
  5. Запускаем, в консоли запускаем карту sdk_vehicles (SP) или dm_lockdown (MP)


Запуск — Способ 2 — Visual Studio

Я рекомендую использовать именно этот способ — не копировать же бинарники мода каждый раз после сборки!


  1. Заходим в свойства проекта (не решения!!!) во вкладку Debugging
  2. В поле Command вписываем:
    путь/до/steam/steamapps/common/Source SDK Base 2013 XXXX/hl2.exe
  3. В поле Working Directory вписываем:
    путь/до/steam/steamapps/common/Source SDK Base 2013 XXXX/
  4. В поле Command Arguments вписываем:
    -game "путь/до/репо/xx/game/mod_xxx/" -debug -dev -console
  5. Сохраняем, запускаем (F5)!
  6. Запускаем, в консоли запускаем карту sdk_vehicles (SP) или dm_lockdown (MP)

Если карта загрузилась и вы можете передвигаться и двигать камеру мышью — сборка успешна!

f8v5p2rlbuia1czaky-4hxzgn2s.png


Первая модификация в коде


Функции семейства Msg ()

Функции Msg(), DevMsg(), Warning(), DevWarning() и ConColorMsg() являются чем-то вроде классического printf(), но в мире программирования под Source SDK. Эти функции так или иначе выводят какой-то текст в консоль разработчика и debug output.

// somewhere in tier0/dbg.h
void Msg( const tchar* pMsg, ... );

// somewhere in code
Msg( "This is a message! %d\n", 42 );


Говорящий пистолет!

Давайте научим пистолет писать сообщение с количеством патронов в магазине:


  1. Откройте src/game/server/hl2/weapon_pistol.cpp (Server (Episodic/HL2)/HL2 DLL/weapon_pistol.cpp)
  2. Найдите там метод void CWeaponPistol::PrimaryAttack( void ) (Где-то вокруг строки 255)
  3. Аккурат после строчки BaseClass::PrimaryAttack(); добавьте какое-нибудь сообщение, например:
    BaseClass::PrimaryAttack(); // где-то на строке 251
    Msg( "weapon_pistol: m_iClip1 = %d\n", m_iClip1 );
  4. Соберите мод, запустите и откройте карту
  5. Поскольку мы писали в аргументы -dev, чит-команды включены по умолчанию, поэтому пишите в консоль пресловутый impulse 101 и пробуйте стрелять из пистолета!

4fzl2lvbadhaimfcminlzxvhtvq.png


Заключение


Чему мы научились?

[Я надеюсь, что] из данного урока мы выяснили:


  • Что вообще такое Source SDK и с чем его едят
  • Как генерировать проекты используя VPC
  • Как печатать что-то в консоль разработчика


Полезные ссылки


© Habrahabr.ru