Ru/Authoring a Logical Entity
Для начала мы создадим логическую энтити которая будет выполнять простейшую работу. Она будет хранит значение и увеличивать его каждый раз когда получает ввод (input) от другой энтити. Когда счетчик достигает заданного нами значения, энтити сгенерирует вывод (output) позволяющий оповестить другие энтити об этом условии.
Создаем CPP файл для новой энтити
- Создаем файл называемый
sdk_logicalentity.cpp
. Этот файл должен быть внутри пакпки dlls, которая, в свою очередь, находится в папке с вашим исходным кодом. Например, если вы установили код вC:\MyMod\src
, то вы должны создать файл изC:\MyMod\src\dlls\sdk_logicalentity.cpp
. - Далее копируем этот код и вставляем его в новый файл.
- В последнею очередь добавляем этот файл в ваш проект server.dll. Если вы открыли
game_sdk.sln
solution, тогда вы можете щелкнуть правой кнопкой на проекте hl в окне Solution Explorer и выбрать Add, затем Add Existing Item.
Обзор кода
Определение класса
class CMyLogicalEntity : public CLogicalEntity { public: DECLARE_CLASS( CMyLogicalEntity, CLogicalEntity ); };
Мы наследуем структуру нашей новой энтити от класса CLogicalEntity
. Этот класс содержит энтити, которыя находятся на стороне сервера и не передают данные на сторону клиента. Также мы будем использовать вспомогательный макрос DECLARE_CLASS
который скрывает от нас некоторые рутинные действия. Унаследовав CMyLogicalEntity
от CLogicalEntity
мы можем использовать тип BaseClass
с этим классом. Это будет важно позднее для обращения к функциональности которую несет CLogicalEntity
от которого мы унаследовали класс.
Связываем класс с именем энтити
Затем мы связываем класс CMyLogicalEntity
с фактической энтитей classname
на которую сможет ссылаться движок.
LINK_ENTITY_TO_CLASS( my_logical_entity, CMyLogicalEntity );
Здесь для класса CMyLogicalEntity
объявляется его имя classname как "my_logical_entity"
. Это имя которое Хаммер и движок будут использовать для ссылки на тип энтити. Имя класса (classname
) отличается от имени назначения (targetname
) энтити, которое является строкой которая идентифицирует одну энтитю или группу энтитей. classname
указывает на все энтити данного типа, тогда как targetname
может связывать несколько разных типов энтитей (например у вас может быть энтитя с именем класса env_splash
которая принадлежит группе энтитей, у каждой из которых targetname
равен splash_group
).
Добавляем переменные в класс
int m_nThreshold; // Пороговое значение срабатывания output int m_nCounter; // Внутренний счетчик
Здесь мы описали две переменные целого типа, которые будут в дальшейшем использоваться в счетчике.
Используем описание данных энтити
. . . public: DECLARE_CLASS( CMyLogicalEntity, CLogicalEntity); DECLARE_DATADESC(); . . . LINK_ENTITY_TO_CLASS( my_logical_entity, CMyLogicalEntity ); BEGIN_DATADESC( CMyLogicalEntity ) DEFINE_FIELD( m_nCounter, FIELD_INTEGER ), DEFINE_KEYFIELD( m_nThreshold, FIELD_INTEGER, "threshold" ), END_DATADESC()
Макрос DECLARE_DATADESC
должен включаться в код для того чтобы компилятор мог знать что мы добавляем описание таблицы данных (data description table) ниже в реализации класса. Описание данных содержит различные определения для переменных и специальных функций для этого класса. В нашем случае, m_nCounter
описывается для сохранения/загрузки значения счетчика, а m_nThreshold
- для того чтобы сообщить игре об использовании значения с именем "threshold"
(конечного значения) для связи этой переменной с значением ключа энтити в Хаммере.
Смотрите документ Таблицы описания данных для дополнительной информации.
Создаем событие вывода (output event)
COutputEvent m_OnThreshold; DEFINE_OUTPUT( m_OnThreshold, "OnThreshold" ),
Это событие будет включаться при встрече описанного конечного значения. Для дополнительной информации смотрите вводы и выводы энтитей.
Создаем функцию ввода (input function)
void InputTick( inputdata_t &inputData ); void CMyLogicalEntity::InputTick( inputdata_t &inputData ) { // Увеличиваем наш счетчик. m_nCounter++; // Проверяем, не превысили ли мы пороговое значение. if ( m_nCounter >= m_nThreshold ) { // Если превысили - вызываем событие output. m_OnThreshold.FireOutput( inputData.pActivator, this ); // Сбрасываем счетчик на ноль. m_nCounter = 0; } }
Эта функция просто увеличивает счетчик и генерирует событие output когда значение счетчика достигает конечного значения, как это указано в свойстве энтити в Хамере. Данная функция не извлекает никаких значений из Хаммера.
Создаем запись в FGD файле
Для использования энтити в Хаммере, мы должны создать запись в FGD файле. Смотрите документ FGD формата для дополнительной информации о FGD файлах.
Если вы ещё не создали .FGD файл для вашего мода, вы наверное это сейчас захотите сделать. Чтобы сделать это создайте пустой файл с расширением .FGD гденибудь на вашем жестком диске (лучше положить его в папку с вашим модом). Вставьте код внизу в этот файл. Перейдите в Хаммер и выберите Tools->Options и добавьте .FGD файл в секцию Game Data files
. Диалог Game Configurations описан в этом документе.
Затем мы объявляем знвчение "threshold" связанное с переменной m_nThreshold
, функцией ввода Tick
и функцией вывода OnThreshold
.
@PointClass base(Targetname) = my_logical_entity : "Tutorial logical entity." [ threshold(integer) : "Threshold" : 1 : "Threshold value." input Tick(void) : "Adds one tick to the entity's count." output OnThreshold(void) : "Threshold was hit." ]
Если ваш .FGD не пустой, убедитесь что добавили строку @include "base.fgd"
, которая даст вам некоторые нужные функции Хаммера.