Shambler team
Статьи по программированию под движком Gold Source (игры Half-Life 1) и работе с SDK

Рипперам Спирита посвящается...

Наверное многие хотят себя попробовать не только в области маппинга, но и в программировании, устав, от бесконечных ограничений обычного ХЛ. И тут на помощь мапперам приходит Спирит (мод Spirit of Half-Life), в котором возможно многое, по прежнему не затрагивая кодинг. Однако Cпирит обладает кучей нехороших ошибок, которые боюсь исправить будет не так просто. Что же делать в случае, если из всего громадного кода Спирита нужен всего лишь env_rain, а так хочется, чтобы и вагончики тоже работали нормально — ответ прост, нужно перетащить код дождя в свой мод. Зачастую именно с этого и начинают свой путь будущие кодеры. Причем именно со Спирита, так как исходники других модов обычно недоступны. Многие пытаются сделать что-то по учебникам и руководствам, однако в руководстве более или менее подробно расписано, как написать код для той или иной штуки, тогда как с исходниками Спирита новичок остается "один на один", к тому же Спирит — система глобальная, и перетащить всё что угодно, обойдясь "малой кровью" получится далеко не у каждого. Рассмотреть основные трудности, которые возникают у новичков при рипании Спирита и призвано это руководство.

Первые трудности

Для работы нам понадобятся SDK Спирита (любой, который вам нужен) и SDK Half-Life — можно взять версию 2.2 или 2.3, но я рекомендую версию 2.1, как наиболее быструю и безглючную. Ну как вы понимаете, чтобы зарипать энтитю нужно для начала найти её вывод в энтитю, а именно строчку LNIK_ENTITY_TO_CLASS в которой будет написано и название энтити. После этого смело выделяйте все функции, которые относятся к данному объекту-энтите (у них будет одинаковое название, ну например у func_tank будут названия всех void'ов и bool'ей начинаться с void CFuncTank :: или BOOL CFuncTank :: ) и копируйте их в свой код, примерно на то же место, где они находятся в Спирите, если же они находятся в новом файле — создайте аналогичный файл у себя и добавьте его в проект. После чего запускайте компиляцию и смотрите на ошибки, которые выдаст вам компилятор.

Ошибки

Первая и наиболее распространенная ошибка имеет следующий вид:

SetNextThink undeclare identifier.

Не пытайтесь перетащить эту функцию в свой код, ибо это — глобальная утилита movewith (в смысле система movewith её активно использует), и Вам она абсолютно не нужна (ну разумеется если Вы не хотите перетащить movewith в свой код). Рассмотрим как же исправить эту ошибку. Строка, на которую поругался компилятор будет иметь примерно следующий вид:

SetNextThink (0.5);

Разумеется число там может быть любым другим. Исправлять это мы будем следующим способом. Замените данную строку на:
pev->nextthink = gpGlobals->time + 0.5;

разумеется число нужно подставлять то, которое вы увидели в скобках. Иногда данная строка имеет немного другой вид:
SetNextThink (0.5, FALSE);

В этом случае нужно будет заменить ее немного другой строкой, а именно :
pev->nextthink = pev->ltime + 0.5;

Значение 0.5 в обоих случаях дано просто для примера, Вам могут встретиться любые значения, даже какая-либо переменная, в любом случае мы дописываем ее так, как показано на примере.


Пойдем дальше. Вторая распространенная ошибка, это —

DontThink undeclare identifier.

Эту ошибку исправить ещё проще, просто замените строку

DontThink();

на
pev->nextthink = 0;


Третья, часто встречающаяся ошибка — ругань компилятора на стринг at_debug, тогда просто замените все слова at_debug на at_console, это можно сделать и в автоматическом режиме — т.е. автозаменой.


Иногда компилятор ругается на неизвестную функцию DesiredAction — это так же утилита movewith, которой нет в ХЛ, поэтому просто переименуйте DesiredAction в Think (а если функция Think уже есть — перенесите туда все из DesiredAction).

Глобальной функции Activate в Half-Life также нет — зачастую данную функцию можно просто удалить, но внимательно следите, что в этой функции находится, если эта функция имеет вид, типа:

void CParticle::Activate( void )
{
CPointEntity::Activate();
UTIL_DesiredAction(this);
}
смело грохайте её, а вот если у функции такой вид:
void CEnvSky :: Activate ( void )
{
pev->effects |= EF_NODRAW;
pev->nextthink = gpGlobals->time + 1.0;
}
то переименуйте Activate в Spawn (не забудьте также продекларировать её). Кстати не стоит обольщаться тем, что функции типа env_fog или env_sky такие простые — на самом деле большая часть кода находится в клиенте, куда Вам, если вы начинающий кодер, я лезть не советую, поскольку в клиенте запутаться ещё проще, нежели в сервере. Если компилятор ругается на какой-то локус — смело комментируйте (или выбрасывайте совсем из кода) данные строки — они Вам также не понадобятся, если конечно Вы не хотите перетащить локус к себе, а сделать это будет не так-то просто, поскольку локус — система глобальная. Если энтити брашевые, то в них частенько встречаются подобные условия
if (m_pMoveWith)
{
m_yawCenter = pev->angles.y - m_pMoveWith->pev->angles.y;
m_pitchCenter = pev->angles.x - m_pMoveWith->pev->angles.x;
}
else
{
m_yawCenter = pev->angles.y;
m_pitchCenter = pev->angles.x;
}
в таком случае нужно поступить следующим образом, обрезав почти всё, и оставив только это
m_yawCenter = pev->angles.y;
m_pitchCenter = pev->angles.x;


Так же часто компилятор ругается на UTIL_SetOrigin, в которой он не может конвертировать int в pev или что-то типа того. При этом данная строка имеет примерно такой вид:

UTIL_SetOrigin( this, pev->origin );
заменяется она на
UTIL_SetOrigin( pev, pev->origin );
Вам может встретиться случай и посложнее, например
UTIL_SetOrigin( m_pSpot, tr.vecEndPos );
В данном случае заменять m_pSpot на pev нельзя ни в коем случае, нужно просто указать, что m_pSpot входит в pev. См. пример:
UTIL_SetOrigin( m_pSpot->pev, tr.vecEndPos );

Кстати строки, подобные

UTIL_SetAvelocity(this, g_vecZero);
UTIL_FlushAliases();
можете смело удалять — они Вам не понадобятся. Данных советов должно хватить, чтобы перетащить из Спирта несложные энтити, типа env_decal, env_shokwave, env_model и прочих несложных энтитей, а для новичка большего и не нужно. Потом, когда Вы поднаберётесь опыта, Вы сможете перетащить любую энтитю, будь то movewith или локус.

Подсказки и полезные советы от человека, который перетащил movewith в обычный ХЛ :)г .

Предполагается, что Вы уже имеете достаточно опыта, чтобы перенести тот же movewith, но иногда попадаются такие ошибки, что хоть стой, хоть падай, а толку = 0. Вот про такие вещи я дам Вам несколько советов.

  1. Если вы перетащили movewith, а приаттаченные энтити не обновляются во время движения — Вы упустили важную функцию в файле player.cpp (там по-моему всего три строки, но тем не менее).
  2. Так же при подрубании movewith обычный use перестает работать в player.cpp. Найдите функцию use и посмотрите, чего дописал туда Лаури.
  3. Отражения моделей находятся в файле studiomodelrenderer.cpp (ключевое слово поиска — reflection). Так же там придётся прописать в файл const.h новый тип render fx.
  4. Управление любой целью с помощью префиксов + и - находятся в файле subs.cpp (ключевое слово поиска — '+').
  5. Консольная команда fire находится в client.cpp (я думаю не нужно объяснять по какому слову искать код).

Заключение

Надеюсь, что вышеприведенное руководство поможет начинающим кодерам, в освоении таскания энтитей, ибо кодинг в ХЛ на 40% заключается именно в этом :D. Если возникнут какие-то вопросы, или у Вас случится ошибка, которую я не включил в своё руководство — пишите, и я подробно разберу, как от неё избавиться.

Спасибо за внимание

g-cont

2004 Shambler Team
  Counter.CO.KZ -     !
Hosted by uCoz