Статьи по программированию под движком 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);
можете смело удалять — они Вам не понадобятся. Данных советов должно хватить,
чтобы перетащить из Спирта несложные энтити, типа env_decal, env_shokwave, env_model и
прочих несложных энтитей, а для новичка большего и не нужно.
Потом, когда Вы поднаберётесь опыта, Вы сможете перетащить любую энтитю, будь то movewith или локус.
Подсказки и полезные советы от человека, который перетащил movewith
в обычный ХЛ :)г .
Предполагается, что Вы уже имеете достаточно опыта,
чтобы перенести тот же movewith, но иногда попадаются такие ошибки, что хоть стой, хоть падай, а толку = 0.
Вот про такие вещи я дам Вам несколько советов.
- Если вы перетащили movewith, а приаттаченные энтити не обновляются во время движения — Вы
упустили важную функцию в файле player.cpp (там по-моему всего три строки, но тем не менее).
- Так же при подрубании movewith обычный use перестает работать в player.cpp.
Найдите функцию use и посмотрите, чего дописал туда Лаури.
- Отражения моделей находятся в файле studiomodelrenderer.cpp
(ключевое слово поиска — reflection). Так же там придётся прописать в файл const.h новый тип render fx.
- Управление любой целью с помощью префиксов + и - находятся в файле subs.cpp (ключевое слово поиска — '+').
- Консольная команда fire находится в client.cpp (я думаю не нужно объяснять по какому слову искать код).
Заключение
Надеюсь, что вышеприведенное руководство поможет начинающим кодерам,
в освоении таскания энтитей, ибо кодинг в ХЛ на 40% заключается именно в этом :D.
Если возникнут какие-то вопросы, или у Вас случится ошибка, которую я не включил в своё руководство —
пишите, и я подробно разберу, как от неё избавиться.
Спасибо за внимание
g-cont
|